Petr Salinger wrote: > It effectively test return code of > > fprintf (fp, "%2147483648d%2147483648d", 1, 1); > > The printf family returns int and should return number of written bytes. > It therefore cannot exceed MAX_INT. > > But the test tries to print twice entry with width MAX_INT+1. > I would understand the test with i.e. 2147483640 > or six time 512 MB.
Yeah, your suggested test would be a more precise test for the original bug[1]. C99 (N1256 ยง7.19.6.1.4) only tells us that the field width is a "nonnegative decimal integer". It would be nice to clarify with the C working group whether a field width that doesn't fit into an "int" triggers undefined behavior or if the implementation is obligated to catch it. > On kfreebsd-amd64, it tries to > mmap(0,0xffffffff80001000,PROT_READ|PROT_WRITE,MAP_ANON|MAP_TYPE|MAP_PRIVATE,0xffffffff,0) > and fails. Sounds buggy. In fact, there are at least a couple of seemingly buggy aspects here. - read_int does not check for overflow - read_int returns "unsigned int", but "prec" and "width" are ints - the "for (; (size_t) nspecs_done < nspecs; ++nspecs_done)" loop does not check for overflow when deciding the initial work buffer size - the private __parse_one_spec API (and public parse_printf_format API) does not seem to include a way to indicate overflow Anyway, how about this patch? It implements your 6 times 512 MiB idea (well, 3 times 1 GiB because I'm lazy) and adds a new test for the related bug Robert found (which gets masked on Linux by malloc() not bothering to try to fulfill such huge requests --- maybe it would be possible to tweak it so it can fail on Linux, too). --- [1] http://sourceware.org/bugzilla/show_bug.cgi?id=5424 stdio-common/Makefile | 2 +- stdio-common/bug22.c | 5 +++-- stdio-common/bug22a.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 stdio-common/bug22a.c diff --git a/stdio-common/Makefile b/stdio-common/Makefile index 006f5468..3be668cc 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -60,7 +60,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \ tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \ bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \ - scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 + bug22a scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 test-srcs = tst-unbputc tst-printf diff --git a/stdio-common/bug22.c b/stdio-common/bug22.c index 2228388b..1f59c735 100644 --- a/stdio-common/bug22.c +++ b/stdio-common/bug22.c @@ -1,7 +1,8 @@ /* BZ #5424 */ #include <stdio.h> -#define N 2147483648 +/* 1 GiB * 3 > INT_MAX bytes */ +#define N 1073741824 #define STRINGIFY(S) #S #define MAKE_STR(S) STRINGIFY(S) @@ -20,7 +21,7 @@ do_test (void) return 1; } - ret = fprintf (fp, "%" SN "d%" SN "d", 1, 1); + ret = fprintf (fp, "%" SN "d%" SN "d%" SN "d", 1, 1); printf ("ret = %d\n", ret); diff --git a/stdio-common/bug22a.c b/stdio-common/bug22a.c new file mode 100644 index 00000000..37efea39 --- /dev/null +++ b/stdio-common/bug22a.c @@ -0,0 +1,33 @@ +/* Not in BZ yet */ +#include <stdio.h> + +/* 2 GiB == INT_MAX + 1 */ +#define N 2147483648 + +#define STRINGIFY(S) #S +#define MAKE_STR(S) STRINGIFY(S) + +#define SN MAKE_STR(N) + +static int +do_test (void) +{ + int ret; + + FILE *fp = fopen ("/dev/null", "w"); + if (fp == NULL) + { + puts ("cannot open /dev/null"); + return 1; + } + + ret = fprintf (fp, "%" SN "d", 1, 1); + + printf ("ret = %d\n", ret); + + return ret != -1; +} + +#define TIMEOUT 30 +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" -- 1.7.7.rc1 -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org