re PR sanitizer/80403 (UBSAN: compile time crash with "type mismatch in binary expres...
authorJakub Jelinek <jakub@redhat.com>
Wed, 12 Apr 2017 18:08:29 +0000 (20:08 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 12 Apr 2017 18:08:29 +0000 (20:08 +0200)
PR sanitizer/80403
PR sanitizer/80404
PR sanitizer/80405
* fold-const.c (fold_ternary_loc): Use op1 instead of arg1 as argument
to fold_build2_loc.  Convert TREE_OPERAND (tem, 0) to type.  Use
op0 instead of fold_convert_loc (loc, type, arg0).

* g++.dg/ubsan/pr80403.C: New test.
* g++.dg/ubsan/pr80404.C: New test.
* g++.dg/ubsan/pr80405.C: New test.

From-SVN: r246881

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ubsan/pr80403.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ubsan/pr80404.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ubsan/pr80405.C [new file with mode: 0644]

index 89af9cc..efd66a6 100644 (file)
@@ -1,3 +1,12 @@
+2017-04-12  Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/80403
+       PR sanitizer/80404
+       PR sanitizer/80405
+       * fold-const.c (fold_ternary_loc): Use op1 instead of arg1 as argument
+       to fold_build2_loc.  Convert TREE_OPERAND (tem, 0) to type.  Use
+       op0 instead of fold_convert_loc (loc, type, arg0).
+
 2017-04-12  Jeff Law  <law@redhat.com>
 
        * genattrtab.c (write_eligible_delay): Verify DELAY_INSN still
index 2f2e93a..fb0b1a6 100644 (file)
@@ -11508,10 +11508,12 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          STRIP_NOPS (tem);
          if (TREE_CODE (tem) == RSHIFT_EXPR
              && tree_fits_uhwi_p (TREE_OPERAND (tem, 1))
-              && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
-                tree_to_uhwi (TREE_OPERAND (tem, 1)))
+              && (unsigned HOST_WIDE_INT) tree_log2 (arg1)
+                == tree_to_uhwi (TREE_OPERAND (tem, 1)))
            return fold_build2_loc (loc, BIT_AND_EXPR, type,
-                               TREE_OPERAND (tem, 0), arg1);
+                                   fold_convert_loc (loc, type,
+                                                     TREE_OPERAND (tem, 0)),
+                                   op1);
        }
 
       /* A & N ? N : 0 is simply A & N if N is a power of two.  This
@@ -11542,7 +11544,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type)))
        return fold_build2_loc (loc, code == VEC_COND_EXPR ? BIT_AND_EXPR
                                                           : TRUTH_ANDIF_EXPR,
-                               type, fold_convert_loc (loc, type, arg0), arg1);
+                               type, op0, op1);
 
       /* Convert A ? B : 1 into !A || B if A and B are truth values.  */
       if (code == VEC_COND_EXPR ? integer_all_onesp (op2) : integer_onep (op2)
@@ -11558,7 +11560,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
                                         ? BIT_IOR_EXPR
                                         : TRUTH_ORIF_EXPR,
                                    type, fold_convert_loc (loc, type, tem),
-                                   arg1);
+                                   op1);
        }
 
       /* Convert A ? 0 : B into !A && B if A and B are truth values.  */
index f43a4d9..9dce05e 100644 (file)
@@ -1,5 +1,12 @@
 2017-04-12  Jakub Jelinek  <jakub@redhat.com>
 
+       PR sanitizer/80403
+       PR sanitizer/80404
+       PR sanitizer/80405
+       * g++.dg/ubsan/pr80403.C: New test.
+       * g++.dg/ubsan/pr80404.C: New test.
+       * g++.dg/ubsan/pr80405.C: New test.
+
        PR c/80163
        * gcc.dg/torture/pr80163.c: New test.
 
diff --git a/gcc/testsuite/g++.dg/ubsan/pr80403.C b/gcc/testsuite/g++.dg/ubsan/pr80403.C
new file mode 100644 (file)
index 0000000..e249f9b
--- /dev/null
@@ -0,0 +1,11 @@
+// PR sanitizer/80403
+// { dg-do compile }
+// { dg-options "-fsanitize=undefined" }
+
+unsigned
+foo ()
+{
+  unsigned a = (unsigned) (!(6044238 >> 0) >= (0 < 0)) % 0;    // { dg-warning "division by zero" }
+  unsigned b = (unsigned) (!(6044238 >> 0) >= (0 < 0)) / 0;    // { dg-warning "division by zero" }
+  return a + b;
+}
diff --git a/gcc/testsuite/g++.dg/ubsan/pr80404.C b/gcc/testsuite/g++.dg/ubsan/pr80404.C
new file mode 100644 (file)
index 0000000..b3fa7c2
--- /dev/null
@@ -0,0 +1,12 @@
+// PR sanitizer/80404
+// { dg-do compile }
+// { dg-options "-fsanitize=undefined" }
+
+extern short v;
+
+unsigned
+foo ()
+{
+  unsigned a = (0 < 0 >= (0 >= 0)) / (unsigned) v;
+  return a;
+}
diff --git a/gcc/testsuite/g++.dg/ubsan/pr80405.C b/gcc/testsuite/g++.dg/ubsan/pr80405.C
new file mode 100644 (file)
index 0000000..30a9b1a
--- /dev/null
@@ -0,0 +1,11 @@
+// PR sanitizer/80405
+// { dg-do compile }
+// { dg-options "-fsanitize=undefined" }
+
+extern unsigned int v, w;
+
+void
+foo ()
+{
+  w = (!~0 >= (unsigned) (0 < 0)) << v;
+}