re PR sanitizer/58413 (ubsan constant folding)
authorMarek Polacek <polacek@redhat.com>
Wed, 25 Sep 2013 08:58:57 +0000 (08:58 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Wed, 25 Sep 2013 08:58:57 +0000 (08:58 +0000)
PR sanitizer/58413
c-family/
* c-ubsan.c (ubsan_instrument_shift): Don't instrument
an expression if we can prove it is correct.
(ubsan_instrument_division): Likewise.  Remove unnecessary
check.
testsuite/
* c-c++-common/ubsan/shift-5.c: New test.
* c-c++-common/ubsan/shift-6.c: New test.
* c-c++-common/ubsan/div-by-zero-5.c: New test.
* gcc.dg/ubsan/c-shift-1.c: New test.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
From-SVN: r202886

gcc/c-family/ChangeLog
gcc/c-family/c-ubsan.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/shift-5.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/shift-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/ubsan/c-shift-1.c [new file with mode: 0644]

index 1772ba56b490604dd09963cbac3d3bb62acf3d46..c7a8c7872cc5e5870b9fd6e2e8f653e0e2fd6528 100644 (file)
@@ -1,3 +1,12 @@
+2013-09-25  Marek Polacek  <polacek@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/58413
+       * c-ubsan.c (ubsan_instrument_shift): Don't instrument
+       an expression if we can prove it is correct.
+       (ubsan_instrument_division): Likewise.  Remove unnecessary
+       check.
+
 2013-09-18  Marek Polacek  <polacek@redhat.com>
 
        PR sanitizer/58411
index 9f43f6d55b84084fce0dd4556b95509f371e7c69..0bfc660cdd5b7de72cfe0f4965efd41487ab0b2b 100644 (file)
@@ -51,14 +51,6 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
   if (TREE_CODE (type) != INTEGER_TYPE)
     return NULL_TREE;
 
-  /* If we *know* that the divisor is not -1 or 0, we don't have to
-     instrument this expression.
-     ??? We could use decl_constant_value to cover up more cases.  */
-  if (TREE_CODE (op1) == INTEGER_CST
-      && integer_nonzerop (op1)
-      && !integer_minus_onep (op1))
-    return NULL_TREE;
-
   t = fold_build2 (EQ_EXPR, boolean_type_node,
                    op1, build_int_cst (type, 0));
 
@@ -74,6 +66,11 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
       t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
     }
 
+  /* If the condition was folded to 0, no need to instrument
+     this expression.  */
+  if (integer_zerop (t))
+    return NULL_TREE;
+
   /* In case we have a SAVE_EXPR in a conditional context, we need to
      make sure it gets evaluated before the condition.  */
   t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
@@ -138,6 +135,11 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
       tt = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, x, tt);
     }
 
+  /* If the condition was folded to 0, no need to instrument
+     this expression.  */
+  if (integer_zerop (t) && (tt == NULL_TREE || integer_zerop (tt)))
+    return NULL_TREE;
+
   /* In case we have a SAVE_EXPR in a conditional context, we need to
      make sure it gets evaluated before the condition.  */
   t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
index 68e38cc94196c2090309a4d42da24d6fc92573d1..09644d2103746d1c61fbf562c3ca7305e116d363 100644 (file)
@@ -1,3 +1,11 @@
+2013-09-25  Marek Polacek  <polacek@redhat.com>
+
+       PR sanitizer/58413
+       * c-c++-common/ubsan/shift-5.c: New test.
+       * c-c++-common/ubsan/shift-6.c: New test.
+       * c-c++-common/ubsan/div-by-zero-5.c: New test.
+       * gcc.dg/ubsan/c-shift-1.c: New test.
+
 2013-09-25  Marek Polacek  <polacek@redhat.com>
 
        PR c++/58516
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c
new file mode 100644 (file)
index 0000000..7a28bac
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile} */
+/* { dg-options "-fsanitize=integer-divide-by-zero" } */
+
+void
+foo (void)
+{
+  int A[-2 / -1] = {};
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-5.c b/gcc/testsuite/c-c++-common/ubsan/shift-5.c
new file mode 100644 (file)
index 0000000..6f9c52a
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=shift -w" } */
+/* { dg-shouldfail "ubsan" } */
+
+int x;
+int
+foo (void)
+{
+  /* None of the following should pass.  */
+  switch (x)
+    {
+    case 1 >> -1:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 12 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 12 } */
+    case -1 >> -1:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 15 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 15 } */
+    case 1 << -1:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 18 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 18 } */
+    case -1 << -1:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 21 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 21 } */
+    case -1 >> 200:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 24 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 24 } */
+    case 1 << 200:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 27 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 27 } */
+      return 1;
+    }
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-6.c b/gcc/testsuite/c-c++-common/ubsan/shift-6.c
new file mode 100644 (file)
index 0000000..a0e2e20
--- /dev/null
@@ -0,0 +1,30 @@
+/* PR sanitizer/58413 */
+/* { dg-do run { target int32plus } } */
+/* { dg-options "-fsanitize=shift -w" } */
+
+int x = 7;
+int
+main (void)
+{
+  /* All of the following should pass.  */
+  int A[128 >> 5] = {};
+  int B[128 << 5] = {};
+
+  static int e =
+    ((int)
+     (0x00000000 | ((31 & ((1 << (4)) - 1)) << (((15) + 6) + 4)) |
+      ((0) << ((15) + 6)) | ((0) << (15))));
+
+  if (e != 503316480)
+    __builtin_abort ();
+
+  switch (x)
+    {
+    case 1 >> 4:
+    case 1 << 4:
+    case 128 << (4 + 1):
+    case 128 >> (4 + 1):
+      return 1;
+    }
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c
new file mode 100644 (file)
index 0000000..61b9010
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile} */
+/* { dg-options "-fsanitize=shift -w" } */
+/* { dg-shouldfail "ubsan" } */
+
+int x;
+int
+main (void)
+{
+  /* None of the following should pass.  */
+  int A[1 >> -1] = {};    /* { dg-error "variable-sized object may not be initialized" } */
+  int B[-1 >> -1] = {};   /* { dg-error "variable-sized object may not be initialized" } */
+  int D[1 << -1] = {};    /* { dg-error "variable-sized object may not be initialized" } */
+  int E[-1 << -1] = {};   /* { dg-error "variable-sized object may not be initialized" } */
+  int F[-1 >> 200] = {};  /* { dg-error "variable-sized object may not be initialized" } */
+  int G[1 << 200] = {};   /* { dg-error "variable-sized object may not be initialized" } */
+
+  return 0;
+}