Hi!

Last week I've finally decided to find time to look into sometimes very
weird signed-integer-overflow runtime messages, which report that say
signed integer overflow: 1234567890123456 \\* 1234567890123456 cannot be 
represented in type 'long int[10]'
Obviously the integer overflow is not happening in an array type.

The problem is that ubsan_type_descriptor needs for a couple of spots the
element type and changes the type parameter to the element type, but then
it adds the result into the hash table using that type, instead of the
TYPE_MAIN_VARIANT of the type with which the function has been originally
called, so if we first record say bounds violation on long int[10],
we actually create "long int[10]" object and record it for long int type,
and then when we look up long int, we get this (and lookup for long int[10]
next time isn't successful and creates another object).

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk and release branches?

2017-07-31  Jakub Jelinek  <ja...@redhat.com>

        PR sanitizer/81604
        * ubsan.c (ubsan_type_descriptor): For UBSAN_PRINT_ARRAY don't
        change type to the element type, instead add eltype variable and
        use it where we are interested in the element type.

        * c-c++-common/ubsan/pr81604.c: New test.

--- gcc/ubsan.c.jj      2017-07-28 12:35:27.000000000 +0200
+++ gcc/ubsan.c 2017-07-28 18:11:21.686219421 +0200
@@ -402,6 +402,7 @@ ubsan_type_descriptor (tree type, enum u
     /* We weren't able to determine the type name.  */
     tname = "<unknown>";
 
+  tree eltype = type;
   if (pstyle == UBSAN_PRINT_POINTER)
     {
       pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
@@ -452,12 +453,12 @@ ubsan_type_descriptor (tree type, enum u
       pp_quote (&pretty_name);
 
       /* Save the tree with stripped types.  */
-      type = t;
+      eltype = t;
     }
   else
     pp_printf (&pretty_name, "'%s'", tname);
 
-  switch (TREE_CODE (type))
+  switch (TREE_CODE (eltype))
     {
     case BOOLEAN_TYPE:
     case ENUMERAL_TYPE:
@@ -467,9 +468,9 @@ ubsan_type_descriptor (tree type, enum u
     case REAL_TYPE:
       /* FIXME: libubsan right now only supports float, double and
         long double type formats.  */
-      if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
-         || TYPE_MODE (type) == TYPE_MODE (double_type_node)
-         || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
+      if (TYPE_MODE (eltype) == TYPE_MODE (float_type_node)
+         || TYPE_MODE (eltype) == TYPE_MODE (double_type_node)
+         || TYPE_MODE (eltype) == TYPE_MODE (long_double_type_node))
        tkind = 0x0001;
       else
        tkind = 0xffff;
@@ -478,7 +479,7 @@ ubsan_type_descriptor (tree type, enum u
       tkind = 0xffff;
       break;
     }
-  tinfo = get_ubsan_type_info_for_type (type);
+  tinfo = get_ubsan_type_info_for_type (eltype);
 
   /* Create a new VAR_DECL of type descriptor.  */
   const char *tmp = pp_formatted_text (&pretty_name);
--- gcc/testsuite/c-c++-common/ubsan/pr81604.c.jj       2017-07-28 
18:20:52.471352034 +0200
+++ gcc/testsuite/c-c++-common/ubsan/pr81604.c  2017-07-28 18:25:54.398733100 
+0200
@@ -0,0 +1,31 @@
+/* PR sanitizer/81604 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds,signed-integer-overflow" } */
+
+long a[10];
+
+__attribute__((noinline, noclone)) long *
+foo (int i)
+{
+  return &a[i];
+}
+
+__attribute__((noinline, noclone)) long
+bar (long x, long y)
+{
+  return x * y;
+}
+
+int
+main ()
+{
+  volatile int i = -1;
+  volatile long l = __LONG_MAX__;
+  long *volatile p;
+  p = foo (i);
+  l = bar (l, l);
+  return 0;
+}
+
+/* { dg-output "index -1 out of bounds for type 'long int 
\\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*signed integer overflow: \[0-9]+ \\* \[0-9]+ cannot 
be represented in type 'long int'" } */

        Jakub

Reply via email to