This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] avoid using types wider than int for width and precision (PR 80364)


Bug 80364 - sanitizer detects signed integer overflow in
gimple-ssa-sprintf.c, points out a runtime error (integer
overflow when negating LONG_MIN) triggered by the undefined
saniziter for an invalid test case recently added to the test
suite.  The test case passes an argument of type long as
the width and precision specified by the asterisk where
the argument is required to be an int.

The attached fix avoids this error by using the expected type
(int) rather than the type of actual argument.

This is a 7.0 P1 regression so I'm looking for approval to
commit the patch to the trunk.

Martin
PR middle-end/80364 - sanitizer detects signed integer overflow in gimple-ssa-sprintf.c

gcc/ChangeLog:

	PR middle-end/80364
	* gimple-ssa-sprintf.c (get_int_range): Use the specified type when
	recursing, not that of the argument.

gcc/testsuite/ChangeLog:

	PR middle-end/80364
	* gcc.dg/tree-ssa/builtin-sprintf-warn-16.c: New test.

diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 2474391..fbcf5c7 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -961,10 +961,10 @@ get_int_range (tree arg, tree type, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
       /* True if the argument's range cannot be determined.  */
       bool unknown = true;
 
-      type = TREE_TYPE (arg);
+      tree argtype = TREE_TYPE (arg);
 
       if (TREE_CODE (arg) == SSA_NAME
-	  && TREE_CODE (type) == INTEGER_TYPE)
+	  && TREE_CODE (argtype) == INTEGER_TYPE)
 	{
 	  /* Try to determine the range of values of the integer argument.  */
 	  wide_int min, max;
@@ -972,11 +972,11 @@ get_int_range (tree arg, tree type, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
 	  if (range_type == VR_RANGE)
 	    {
 	      HOST_WIDE_INT type_min
-		= (TYPE_UNSIGNED (type)
-		   ? tree_to_uhwi (TYPE_MIN_VALUE (type))
-		   : tree_to_shwi (TYPE_MIN_VALUE (type)));
+		= (TYPE_UNSIGNED (argtype)
+		   ? tree_to_uhwi (TYPE_MIN_VALUE (argtype))
+		   : tree_to_shwi (TYPE_MIN_VALUE (argtype)));
 
-	      HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (type));
+	      HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (argtype));
 
 	      *pmin = min.to_shwi ();
 	      *pmax = max.to_shwi ();
@@ -1004,6 +1004,9 @@ get_int_range (tree arg, tree type, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
 	    *pmin = *pmax = -*pmin;
 	  else
 	    {
+	      /* Make sure signed overlow is avoided.  */
+	      gcc_assert (*pmin != HOST_WIDE_INT_MIN);
+
 	      HOST_WIDE_INT tmp = -*pmin;
 	      *pmin = 0;
 	      if (*pmax < tmp)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-16.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-16.c
new file mode 100644
index 0000000..92112b5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-16.c
@@ -0,0 +1,166 @@
+/* PR middle-end/80364 - sanitizer detects signed integer overflow
+   in gimple-ssa-sprintf.c
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wformat-overflow=1 -ftrack-macro-expansion=0" }
+   { dg-require-effective-target int32plus } */
+
+typedef __SIZE_TYPE__  size_t;
+typedef __WCHAR_TYPE__ wchar_t;
+
+void sink (void*);
+void* get_value (void);
+
+/* Return a random width as type T.  */
+#define W(T) *(T*)get_value ()
+
+/* Return a random precision as type T.  */
+#define P(T) *(T*)get_value ()
+
+/* Return a random value as type T.  */
+#define V(T) *(T*)get_value ()
+
+extern char buf[1];
+
+/* Test convenience macro.  */
+#define T(fmt, ...)					\
+  __builtin_sprintf (buf + 1, fmt, __VA_ARGS__);	\
+  sink (buf)
+
+typedef signed char         schar_t;
+typedef unsigned char       uchar_t;
+typedef signed short        sshort_t;
+typedef unsigned short      ushort_t;
+typedef signed int          sint_t;
+typedef unsigned int        uint_t;
+typedef signed long         slong_t;
+typedef unsigned long       ulong_t;
+typedef signed long long    sllong_t;
+typedef unsigned long long  ullong_t;
+
+#if __SIZEOF_INT128__
+typedef __int128_t          sint128_t;
+typedef __uint128_t         uint128_t;
+#else
+/* When __int128_t is not available, repeat the same tests with long long.
+   This is to avoid having to guard the tests below and to avoid making
+   the dg-warning directives conditional.  */
+typedef signed long long    sint128_t;
+typedef unsigned long long  uint128_t;
+#endif
+
+void test_width_cst (void)
+{
+  T ("%*i", W (schar_t), 1);     /* { dg-warning "between 1 and 128 " } */
+  T ("%*i", W (uchar_t), 12);    /* { dg-warning "between 2 and 255 " } */
+
+  T ("%*i", W (sshort_t), 123);  /* { dg-warning "between 3 and 32768 " } */
+  T ("%*i", W (ushort_t), 1234); /* { dg-warning "between 4 and 65535 " } */
+
+  T ("%*i", W (sint_t), 12345);  /* { dg-warning "between 5 and 2147483648" } */
+  T ("%*i", W (uint_t), 123456); /* { dg-warning "between 6 and 2147483648" } */
+
+  /* Exercise calls with invalid arguments (to verify there is no ICE).  */
+  T ("%*li", W (slong_t), 1234567L);  /* { dg-warning "between 7 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%*li", W (ulong_t), 12345678L); /* { dg-warning "between 8 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+
+  T ("%*lli", W (sllong_t), 123456789LL);  /* { dg-warning "between 9 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%*lli", W (ullong_t), 1234567890LL); /* { dg-warning "between 10 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+
+  T ("%*i", W (sint128_t), 0);  /* { dg-warning "between 1 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%*i", W (uint128_t), 1); /* { dg-warning "between 1 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+
+  T ("%*i", W (float), 2);  /* { dg-warning "between 1 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%*i", W (double), 3); /* { dg-warning "between 1 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+}
+
+void test_width_var (void)
+{
+  T ("%*i", W (schar_t), V (schar_t));     /* { dg-warning "between 1 and 128 " } */
+  T ("%*i", W (uchar_t), V (uchar_t));    /* { dg-warning "between 1 and 255 " } */
+
+  T ("%*i", W (sshort_t), V (sshort_t));  /* { dg-warning "between 1 and 32768 " } */
+  T ("%*i", W (ushort_t), V (ushort_t)); /* { dg-warning "between 1 and 65535 " } */
+
+  T ("%*i", W (sint_t), V (sint_t));  /* { dg-warning "between 1 and 2147483648" } */
+  T ("%*i", W (uint_t), V (uint_t)); /* { dg-warning "between 1 and 2147483648" } */
+
+  /* Exercise calls with invalid arguments (to verify there is no ICE).  */
+  T ("%*li", W (slong_t), V (slong_t));  /* { dg-warning "between 1 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%*li", W (ulong_t), V (ulong_t)); /* { dg-warning "between 1 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+
+  T ("%*lli", W (sllong_t), V (sllong_t));  /* { dg-warning "between 1 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%*lli", W (ullong_t), V (ullong_t)); /* { dg-warning "between 1 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+
+  T ("%*i", W (float), V (int));  /* { dg-warning "between 1 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%*i", W (double), V (int)); /* { dg-warning "between 1 and 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+}
+
+void test_precision_cst (void)
+{
+  T ("%.*i", P (schar_t), 1);     /* { dg-warning "between 1 and 127 " } */
+  T ("%.*i", P (uchar_t), 12);    /* { dg-warning "between 2 and 255 " } */
+
+  T ("%.*i", P (sshort_t), 123);  /* { dg-warning "between 3 and 32767 " } */
+  T ("%.*i", P (ushort_t), 1234); /* { dg-warning "between 4 and 65535 " } */
+
+  T ("%.*i", P (sint_t), 12345);  /* { dg-warning "between 5 and 2147483647" } */
+  T ("%.*i", P (uint_t), 123456); /* { dg-warning "between 6 and 2147483647" } */
+
+  /* Exercise calls with invalid arguments (to verify there is no ICE).  */
+  T ("%.*li", P (slong_t), 1234567L);  /* { dg-warning "between 7 and 2147483647" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%.*li", P (ulong_t), 12345678L); /* { dg-warning "between 8 and 2147483647" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+
+  T ("%.*lli", P (sllong_t), 123456789LL);  /* { dg-warning "between 9 and 2147483647" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%.*lli", P (ullong_t), 1234567890LL); /* { dg-warning "between 10 and 2147483647" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+
+  T ("%.*i", W (float), 0);  /* { dg-warning "up to 2147483647" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%.*i", W (double), 1); /* { dg-warning "between 1 and 2147483647" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+}
+
+void test_precision_var (void)
+{
+  T ("%.*i", P (schar_t), V (schar_t));     /* { dg-warning "up to 128 " } */
+  T ("%.*i", P (uchar_t), V (uchar_t));    /* { dg-warning "up to 255 " } */
+
+  T ("%.*i", P (sshort_t), V (sshort_t));  /* { dg-warning "up to 32768 " } */
+  T ("%.*i", P (ushort_t), V (ushort_t)); /* { dg-warning "up to 65535 " } */
+
+  T ("%.*i", P (sint_t), V (sint_t));  /* { dg-warning "up to 2147483648 " } */
+  T ("%.*i", P (uint_t), V (uint_t)); /* { dg-warning "up to 2147483648 " } */
+
+  /* Exercise calls with invalid arguments (to verify there is no ICE).  */
+  T ("%.*li", P (slong_t), V (slong_t));  /* { dg-warning "up to 2147483648 " } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%.*li", P (ulong_t), V (ulong_t)); /* { dg-warning "up to 2147483648 " } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+
+  T ("%.*lli", P (sllong_t), V (sllong_t));  /* { dg-warning "up to 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%.*lli", P (ullong_t), V (ullong_t)); /* { dg-warning "up to 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+
+  T ("%.*i", P (float), V (int));  /* { dg-warning "up to 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+  T ("%.*i", P (double), V (int)); /* { dg-warning "up to 2147483648" } */
+  /* { dg-warning "expects argument of type .int." "" { target *-*-* } .-1 } */
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]