[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#644023: FTBFS on kfreebsd-i386



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




Reply to: