diff mbox series

Fix UB in int_const_binop

Message ID mpt7ebr8yi9.fsf@arm.com
State New
Headers show
Series Fix UB in int_const_binop | expand

Commit Message

Richard Sandiford April 18, 2019, 9:15 a.m. UTC
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.

Tested with bootstrap-ubsan on aarch64-linux-gnu and x86_64-linux-gnu.
OK to install?  (This is a GCC 9 regression FWIW.)

Richard


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

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

Comments

Richard Biener April 18, 2019, 10:21 a.m. UTC | #1
On Thu, Apr 18, 2019 at 11:16 AM Richard Sandiford
<richard.sandiford@arm.com> wrote:
>
> 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.
>
> Tested with bootstrap-ubsan on aarch64-linux-gnu and x86_64-linux-gnu.
> OK to install?  (This is a GCC 9 regression FWIW.)

OK.

Richard.

> Richard
>
>
> 2019-04-18  Richard Sandiford  <richard.sandiford@arm.com>
>
> gcc/
>         * fold-const.c (int_const_binop): Return early on failure.
>
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c    2019-04-04 08:34:52.001938080 +0100
> +++ gcc/fold-const.c    2019-04-18 10:11:12.336697917 +0100
> @@ -1173,7 +1173,6 @@ poly_int_binop (poly_wide_int &res, enum
>  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, co
>      {
>        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
diff mbox series

Patch

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	2019-04-04 08:34:52.001938080 +0100
+++ gcc/fold-const.c	2019-04-18 10:11:12.336697917 +0100
@@ -1173,7 +1173,6 @@  poly_int_binop (poly_wide_int &res, enum
 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, co
     {
       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