Hi!

While Marek has been debugging while some perl test fails when perl is built
with GCC 4.9, we've discovered that it is because of undefined behavior in
it:
...
  && (((UV)1 << NV_PRESERVES_UV_BITS) >
      (UV)(SvIVX(sv) > 0 ? SvIVX(sv) : -SvIVX(sv)))
where SvIVX(sv) can be LONG_MIN, at which point there is undefined behavior
on the negation, but -fsanitize=undefined did detect only other issues in
the same source file and not this one, because fold-const.c folded it into
ABS_EXPR early.

This patch disables such folding, because all the A op 0 ? A : -A
operations this if is trying to optimize will need instrumentation with
-fsanitize=signed-integer-overflow.

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

2014-03-25  Jakub Jelinek  <ja...@redhat.com>

        PR sanitizer/60636
        * fold-const.c (fold_cond_expr_with_comparison): Don't
        fold A op 0 ? A : -A if -fsanitize=undefined.

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

--- gcc/fold-const.c.jj 2014-01-03 11:40:35.000000000 +0100
+++ gcc/fold-const.c    2014-03-24 17:59:45.395445617 +0100
@@ -4718,7 +4718,13 @@ fold_cond_expr_with_comparison (location
              && operand_equal_p (TREE_OPERAND (arg1, 0),
                                  TREE_OPERAND (arg2, 1), 0)
              && operand_equal_p (TREE_OPERAND (arg1, 1),
-                                 TREE_OPERAND (arg2, 0), 0))))
+                                 TREE_OPERAND (arg2, 0), 0)))
+      /* Don't fold this if sanitizing undefined behavior,
+        -A or Y-X might overflow and after folding this we wouldn't
+        be able to detect that.  */
+      && ((flag_sanitize & SANITIZE_SI_OVERFLOW) == 0
+         || !INTEGRAL_TYPE_P (TREE_TYPE (arg01))
+         || TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg01))))
     switch (comp_code)
       {
       case EQ_EXPR:
--- gcc/testsuite/c-c++-common/ubsan/pr60636.c.jj       2014-03-24 
18:04:33.875925324 +0100
+++ gcc/testsuite/c-c++-common/ubsan/pr60636.c  2014-03-24 18:09:18.696419079 
+0100
@@ -0,0 +1,15 @@
+/* PR sanitizer/60636 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined" } */
+
+volatile long long int a;
+
+int
+main ()
+{
+  long long int u = -__LONG_LONG_MAX__ - 1;
+  a = u > 0 ? u : -u;
+  return 0;
+}
+
+/* { dg-output "negation of -9223372036854775808 cannot be represented in type 
'long long int'" } */

        Jakub

Reply via email to