1010#include " src/stdio/fclose.h"
1111#include " src/stdio/ferror.h"
1212#include " src/stdio/fopen.h"
13+ #include " src/stdio/fopencookie.h"
1314#include " src/stdio/fread.h"
1415#endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE
1516
1617#include " src/stdio/fprintf.h"
1718
18- #include " test/UnitTest/Test .h"
19+ #include " src/__support/CPP/limits .h"
1920#include " test/UnitTest/ErrnoCheckingTest.h"
2021#include " test/UnitTest/ErrnoSetterMatcher.h"
22+ #include " test/UnitTest/Test.h"
2123
2224namespace printf_test {
2325#ifndef LIBC_COPT_STDIO_USE_SYSTEM_FILE
2426using LIBC_NAMESPACE::fclose;
2527using LIBC_NAMESPACE::ferror;
2628using LIBC_NAMESPACE::fopen;
29+ using LIBC_NAMESPACE::fopencookie;
2730using LIBC_NAMESPACE::fread;
2831#else // defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE)
2932using ::fclose;
3033using ::ferror;
3134using ::fopen;
35+ using ::fopencookie;
3236using ::fread;
3337#endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE
3438} // namespace printf_test
@@ -86,3 +90,25 @@ TEST(LlvmLibcFPrintfTest, WriteToFile) {
8690
8791 ASSERT_EQ (printf_test::fclose (file), 0 );
8892}
93+
94+ struct NoopStream {};
95+
96+ static ssize_t noop_write (void *, const char *, size_t size) { return size; }
97+
98+ TEST (LlvmLibcFPrintfTest, CharsWrittenOverflow) {
99+ NoopStream stream;
100+ cookie_io_functions_t funcs = {nullptr , &noop_write, nullptr , nullptr };
101+ ::FILE *file = printf_test::fopencookie (&stream, " w" , funcs);
102+ ASSERT_NE (file, nullptr );
103+
104+ // Trigger an overflow in the return value of fprintf by writing more than
105+ // INT_MAX bytes. We do this by printing a string with precision INT_MAX, and
106+ // then one more character.
107+ int max_int = LIBC_NAMESPACE::cpp::numeric_limits<int >::max ();
108+ int result = LIBC_NAMESPACE::fprintf (file, " %*sA" , max_int, " " );
109+
110+ EXPECT_LT (result, 0 );
111+ ASSERT_ERRNO_EQ (EOVERFLOW);
112+
113+ EXPECT_EQ (printf_test::fclose (file), 0 );
114+ }
0 commit comments