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