Fix two ubsan failures (PR85164)
authorRichard Sandiford <richard.sandiford@arm.com>
Thu, 18 Apr 2019 12:29:56 +0000 (12:29 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 18 Apr 2019 12:29:56 +0000 (12:29 +0000)
Two fixes for UB when handling very large offsets.  The calculation in
force_int_to_mode would have been correct if signed integers used modulo
arithmetic, so just switch to unsigned types.  The calculation in
rtx_addr_can_trap_p_1 didn't handle overflow properly, so switch to
known_subrange_p instead (which is supposed to handle all cases).

2019-04-18  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
PR middle-end/85164
* combine.c (force_int_to_mode): Cast the argument rather than
the result of known_alignment.
* rtlanal.c (rtx_addr_can_trap_p_1): Use known_subrange_p.

gcc/testsuite/
PR middle-end/85164
* gcc.dg/pr85164-1.c, gcc.dg/pr85164-2.c: New tests.

From-SVN: r270442

gcc/ChangeLog
gcc/combine.c
gcc/rtlanal.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr85164-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr85164-2.c [new file with mode: 0644]

index e589a9e751752c5c60c4df40f7533d6596f57ba3..8dba1ed7bf3841af3132df8aa0f5957c877bc9b4 100644 (file)
@@ -1,3 +1,10 @@
+2019-04-18  Richard Sandiford  <richard.sandiford@arm.com>
+
+       PR middle-end/85164
+       * combine.c (force_int_to_mode): Cast the argument rather than
+       the result of known_alignment.
+       * rtlanal.c (rtx_addr_can_trap_p_1): Use known_subrange_p.
+
 2019-04-18  Richard Biener  <rguenther@suse.de>
 
        PR debug/90131
index 5616e6b1bacb2a53fa006c121e0a4aaf853aadc3..4de759a8e6bf7cb5b13af592fbb3fcd1b9644929 100644 (file)
@@ -8946,7 +8946,7 @@ force_int_to_mode (rtx x, scalar_int_mode mode, scalar_int_mode xmode,
       /* If X is (minus C Y) where C's least set bit is larger than any bit
         in the mask, then we may replace with (neg Y).  */
       if (poly_int_rtx_p (XEXP (x, 0), &const_op0)
-         && (unsigned HOST_WIDE_INT) known_alignment (const_op0) > mask)
+         && known_alignment (poly_uint64 (const_op0)) > mask)
        {
          x = simplify_gen_unary (NEG, xmode, XEXP (x, 1), xmode);
          return force_to_mode (x, mode, mask, next_select);
index 3873b4098b0beba6ac60b034fbd83ca9799922ff..268a38799d63c8c5a193b49d7fe7738e50894d41 100644 (file)
@@ -521,7 +521,7 @@ rtx_addr_can_trap_p_1 (const_rtx x, poly_int64 offset, poly_int64 size,
 
          return (!known_size_p (decl_size) || known_eq (decl_size, 0)
                  ? maybe_ne (offset, 0)
-                 : maybe_gt (offset + size, decl_size));
+                 : !known_subrange_p (offset, size, 0, decl_size));
         }
 
       return 0;
index ee03b5e9b55f39cf979a791e881e0890ef16f691..451f190b19509b43e7e7e1a6cc2f4b6ce17d5b00 100644 (file)
@@ -1,3 +1,8 @@
+2019-04-18  Richard Sandiford  <richard.sandiford@arm.com>
+
+       PR middle-end/85164
+       * gcc.dg/pr85164-1.c, gcc.dg/pr85164-2.c: New tests.
+
 2019-04-18  Richard Biener  <rguenther@suse.de>
 
        PR debug/90131
diff --git a/gcc/testsuite/gcc.dg/pr85164-1.c b/gcc/testsuite/gcc.dg/pr85164-1.c
new file mode 100644 (file)
index 0000000..4c5995e
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-options "-O2 -w" } */
+a[];
+b;
+c() {
+  unsigned long d;
+  b = a[d - 1 >> 3];
+}
diff --git a/gcc/testsuite/gcc.dg/pr85164-2.c b/gcc/testsuite/gcc.dg/pr85164-2.c
new file mode 100644 (file)
index 0000000..9e9a7db
--- /dev/null
@@ -0,0 +1,4 @@
+/* { dg-options "-O2 -w" } */
+int a;
+long b;
+void c() { b = -9223372036854775807L - 1 - a; }