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