Fix UB in int_const_binop
authorRichard Sandiford <richard.sandiford@arm.com>
Thu, 18 Apr 2019 12:30:36 +0000 (12:30 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 18 Apr 2019 12:30:36 +0000 (12:30 +0000)
When testing PR 85164, the baseline bootstrap-ubsan results had
a lot of failures from int_const_binop.  This is because with the
new overflow handling we can sometimes do:

      poly_res = res;

on an uninitialised res.

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

gcc/
* fold-const.c (int_const_binop): Return early on failure.

From-SVN: r270443

gcc/ChangeLog
gcc/fold-const.c

index 8dba1ed7bf3841af3132df8aa0f5957c877bc9b4..5b8c5acb076af03ab7612d9083aabae666df4b11 100644 (file)
@@ -1,3 +1,7 @@
+2019-04-18  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * fold-const.c (int_const_binop): Return early on failure.
+
 2019-04-18  Richard Sandiford  <richard.sandiford@arm.com>
 
        PR middle-end/85164
index c2884a67519342e23ce8e2d6ee0741fea225edf5..c4257721cfee3e50cfb2d19d29c4f0dd721cdd9a 100644 (file)
@@ -1173,7 +1173,6 @@ tree
 int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2,
                 int overflowable)
 {
-  bool success = false;
   poly_wide_int poly_res;
   tree type = TREE_TYPE (arg1);
   signop sign = TYPE_SIGN (type);
@@ -1183,17 +1182,18 @@ int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2,
     {
       wide_int warg1 = wi::to_wide (arg1), res;
       wide_int warg2 = wi::to_wide (arg2, TYPE_PRECISION (type));
-      success = wide_int_binop (res, code, warg1, warg2, sign, &overflow);
+      if (!wide_int_binop (res, code, warg1, warg2, sign, &overflow))
+       return NULL_TREE;
       poly_res = res;
     }
-  else if (poly_int_tree_p (arg1) && poly_int_tree_p (arg2))
-    success = poly_int_binop (poly_res, code, arg1, arg2, sign, &overflow);
-  if (success)
-    return force_fit_type (type, poly_res, overflowable,
-                          (((sign == SIGNED || overflowable == -1)
-                            && overflow)
-                           | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)));
-  return NULL_TREE;
+  else if (!poly_int_tree_p (arg1)
+          || !poly_int_tree_p (arg2)
+          || !poly_int_binop (poly_res, code, arg1, arg2, sign, &overflow))
+    return NULL_TREE;
+  return force_fit_type (type, poly_res, overflowable,
+                        (((sign == SIGNED || overflowable == -1)
+                          && overflow)
+                         | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)));
 }
 
 /* Return true if binary operation OP distributes over addition in operand