re PR sanitizer/63697 (-fsanitize=undefined doesn't detect some subtraction overflows)
authorJakub Jelinek <jakub@redhat.com>
Fri, 31 Oct 2014 11:18:13 +0000 (12:18 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 31 Oct 2014 11:18:13 +0000 (12:18 +0100)
PR sanitizer/63697
* tree-vrp.c (simplify_internal_call_using_ranges): For subcode ==
MINUS_EXPR, check overflow on vr0.min - vr1.max and vr0.max - vr1.min
instead of vr0.min - vr1.min and vr0.max - vr1.max.

* c-c++-common/ubsan/overflow-sub-3.c: New test.

From-SVN: r216962

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/ubsan/overflow-sub-3.c [new file with mode: 0644]
gcc/tree-vrp.c

index 36bf711..5ffc217 100644 (file)
@@ -1,3 +1,10 @@
+2014-10-31  Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/63697
+       * tree-vrp.c (simplify_internal_call_using_ranges): For subcode ==
+       MINUS_EXPR, check overflow on vr0.min - vr1.max and vr0.max - vr1.min
+       instead of vr0.min - vr1.min and vr0.max - vr1.max.
+
 2014-10-31  Max Ostapenko  <m.ostapenko@partner.samsung.com>
 
        PR ipa/63696
index 3aa9b6b..7892292 100644 (file)
@@ -1,3 +1,8 @@
+2014-10-31  Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/63697
+       * c-c++-common/ubsan/overflow-sub-3.c: New test.
+
 2014-10-30  Marek Polacek  <polacek@redhat.com>
 
        * gcc.dg/diag-aka-1.c: New test.
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-3.c b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-3.c
new file mode 100644 (file)
index 0000000..deec5c4
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=signed-integer-overflow" } */
+
+__attribute__((noinline, noclone)) int
+foo1 (int x, int y)
+{
+  return x - y;
+}
+
+__attribute__((noinline, noclone)) int
+foo2 (int x, int y)
+{
+  unsigned int xa = (unsigned int) x - (__INT_MAX__ - 3);
+  xa &= 3;
+  x = __INT_MAX__ - 3 + xa;
+  unsigned int ya = y + 1U;
+  ya &= 1;
+  y = ya - 1;
+  return x - y;
+}
+
+int
+main ()
+{
+  int xm1, y;
+  for (xm1 = __INT_MAX__ - 4; xm1 < __INT_MAX__; xm1++)
+    for (y = -1; y <= 0; y++)
+      if (foo1 (xm1 + 1, y) != (int) (xm1 + 1U - y)
+         || foo2 (xm1 + 1, y) != (int) (xm1 + 1U - y))
+       __builtin_abort ();
+  return 0;
+}
+/* { dg-output ":7:\[0-9]\[^\n\r]*signed integer overflow: 2147483647 - -1 cannot be represented in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*:19:\[0-9]\[^\n\r]*signed integer overflow: 2147483647 - -1 cannot be represented in type 'int'" } */
index 55c7f7f..fe67230 100644 (file)
@@ -9538,8 +9538,10 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
     }
   else
     {
-      tree r1 = int_const_binop (subcode, vr0.min, vr1.min);
-      tree r2 = int_const_binop (subcode, vr0.max, vr1.max);
+      tree r1 = int_const_binop (subcode, vr0.min,
+                                subcode == MINUS_EXPR ? vr1.max : vr1.min);
+      tree r2 = int_const_binop (subcode, vr0.max,
+                                subcode == MINUS_EXPR ? vr1.min : vr1.max);
       if (r1 == NULL_TREE || TREE_OVERFLOW (r1)
          || r2 == NULL_TREE || TREE_OVERFLOW (r2))
        return false;