This fixes sanitizer/64906 by also pre-evaluating OP1.  The problem
in this testcase is that OP1 is "SAVE_EXPR <f ? 8 : 0>" which can't
be folded any more, but when we're creating the EQ_EXPR -- checking
whether this expression equals zero -- it can be folded further to
"f == 0".  Afterwards we end up with this (crap omitted):

      ret = if (SAVE_EXPR <(long unsigned int) s>;, SAVE_EXPR <f == 0>;)
        {
          __ubsan (..., (SAVE_EXPR <f != 0 ? 8 : 0>)); 
        }
      else
        {
        }, (... / (SAVE_EXPR <f != 0 ? 8 : 0>));

I.e. the SAVE_EXPR <f != 0 ? 8 : 0> would be evaluated inside the if and not
before.  So do what we already do for OP0.

The shift instrumentation should be fine in this regard.

Bootstrapped/regtested on x86_64-linux, ok for trunk and 5?

2015-09-22  Marek Polacek  <pola...@redhat.com>

        PR sanitizer/64906
        * c-ubsan.c (ubsan_instrument_division): Also pre-evaluate OP1.

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

diff --git gcc/c-family/c-ubsan.c gcc/c-family/c-ubsan.c
index e0cce84..d2bc264 100644
--- gcc/c-family/c-ubsan.c
+++ gcc/c-family/c-ubsan.c
@@ -104,6 +104,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree 
op1)
        }
     }
   t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), unshare_expr (op0), t);
+  t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), unshare_expr (op1), t);
   if (flag_sanitize_undefined_trap_on_error)
     tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
   else
diff --git gcc/testsuite/c-c++-common/ubsan/pr64906.c 
gcc/testsuite/c-c++-common/ubsan/pr64906.c
index e69de29..e0ac0ee 100644
--- gcc/testsuite/c-c++-common/ubsan/pr64906.c
+++ gcc/testsuite/c-c++-common/ubsan/pr64906.c
@@ -0,0 +1,12 @@
+/* PR sanitizer/64906 */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -O 
-Werror=maybe-uninitialized" } */
+
+int
+fn1 (int f, int s)
+{
+  int ret = 0;
+  if (f)
+    ret = s / (f ? (unsigned long) 8 : 0);
+  return ret;
+}

        Marek

Reply via email to