Merge cherrypicks of ['googleplex-android-review.googlesource.com/36100204'] into 25Q4-release.

Change-Id: I17f44b7f5e1de035c9eeb2c7676545d06604818d
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 0513ebd..36830c7 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -3096,27 +3096,52 @@
 }
 #endif
 
-TEST(STDIO_TEST, fread_int_overflow) {
-#if defined(__LP64__)
-  if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
+TEST(STDIO_TEST, fread_EOVERFLOW) {
+  TemporaryFile tf;
+  FILE* fp = fopen(tf.path, "r");
+  ASSERT_TRUE(fp != nullptr);
 
-  const size_t too_big_for_an_int = 0x80000000ULL;
-  std::vector<char> buf(too_big_for_an_int);
-  std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/zero", "re"), fclose};
-  ASSERT_EQ(too_big_for_an_int, fread(&buf[0], 1, too_big_for_an_int, fp.get()));
-#else
-  GTEST_SKIP() << "32-bit can't allocate 2GiB";
-#endif
+  volatile size_t big = SIZE_MAX;
+  char buf[BUFSIZ];
+  errno = 0;
+  ASSERT_EQ(0u, fread(buf, big, big, fp));
+  ASSERT_ERRNO(EOVERFLOW);
+  ASSERT_TRUE(ferror(fp));
+  fclose(fp);
 }
 
-TEST(STDIO_TEST, fwrite_int_overflow) {
+TEST(STDIO_TEST, fwrite_EOVERFLOW) {
+  TemporaryFile tf;
+  FILE* fp = fopen(tf.path, "w");
+  ASSERT_TRUE(fp != nullptr);
+
+  volatile size_t big = SIZE_MAX;
+  char buf[BUFSIZ];
+  errno = 0;
+  ASSERT_EQ(0u, fwrite(buf, big, big, fp));
+  ASSERT_ERRNO(EOVERFLOW);
+  ASSERT_TRUE(ferror(fp));
+  fclose(fp);
+}
+
+TEST(STDIO_TEST, fread_fwrite_int_overflow) {
 #if defined(__LP64__)
   if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
 
+  // Historically the implementation used ints where it should have used size_t.
   const size_t too_big_for_an_int = 0x80000000ULL;
   std::vector<char> buf(too_big_for_an_int);
-  std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/null", "we"), fclose};
-  ASSERT_EQ(too_big_for_an_int, fwrite(&buf[0], 1, too_big_for_an_int, fp.get()));
+
+  // We test both fread() and fwrite() in the same function to avoid two tests
+  // both allocating 2GiB of ram at the same time.
+  {
+    std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/zero", "re"), fclose};
+    ASSERT_EQ(too_big_for_an_int, fread(&buf[0], 1, too_big_for_an_int, fp.get()));
+  }
+  {
+    std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/null", "we"), fclose};
+    ASSERT_EQ(too_big_for_an_int, fwrite(&buf[0], 1, too_big_for_an_int, fp.get()));
+  }
 #else
   GTEST_SKIP() << "32-bit can't allocate 2GiB";
 #endif