Fix CordInputStream for huge cord chunks.

PiperOrigin-RevId: 952140260
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
index 12a967d..bc48f60 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -512,9 +512,11 @@
 bool CordInputStream::Next(const void** data, int* size) {
   if (available_ > 0 || NextChunk(0)) {
     *data = data_ + size_ - available_;
-    *size = available_;
-    bytes_remaining_ -= available_;
-    available_ = 0;
+    size_t consumed =
+        std::min(available_, size_t{std::numeric_limits<int>::max()});
+    *size = consumed;
+    bytes_remaining_ -= consumed;
+    available_ -= consumed;
     return true;
   }
   return false;
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index 7a7a022..6a4bc51 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -844,6 +844,37 @@
   EXPECT_EQ(stream.ByteCount(), 10000);
 }
 
+TEST(CordInputStreamTest, HugeCordNodes) {
+  if (sizeof(void*) < 8) {
+    GTEST_SKIP() << "Not enough memory for test.";
+  }
+
+  std::string input_str;
+  // We don't care about the bytes, so avoid the cost.
+  absl::strings_internal::STLStringResizeUninitializedAmortized(
+      &input_str,
+      // Something larger than INT_MAX
+      3'000'000'000);
+  absl::Cord source = absl::MakeCordFromExternal(input_str, [](auto) {});
+  ASSERT_EQ(source.Chunks().begin()->size(), input_str.size());
+
+  const char* expected_next = input_str.data();
+  size_t size_to_go = input_str.size();
+
+  CordInputStream stream(&source);
+  while (size_to_go > 0) {
+    const void* data;
+    int size;
+    ASSERT_TRUE(stream.Next(&data, &size));
+    ASSERT_EQ(data, static_cast<const void*>(expected_next));
+    ASSERT_GT(size, 0);
+    ASSERT_LE(size, size_to_go);
+
+    expected_next += size;
+    size_to_go -= size;
+  }
+}
+
 TEST_F(IoTest, CordIo) {
   CordOutputStream output;
   int size = WriteStuff(&output);