When factoring a*b + a*c to (b + c)*a we have to guard against the
case of a == 0 as after the factoring b + c might overflow in that
case.  Fixed by doing the addition in an unsigned type if required.

Bootstrap / regtest pending on x86_64-unknown-linux-gnu.

Richard.

2015-10-27  Richard Biener  <rguent...@suse.de>

        PR middle-end/66313
        * fold-const.c (fold_plusminus_mult_expr): If the factored
        factor may be zero use a wrapping type for the inner operation.

        * c-c++-common/ubsan/pr66313.c: New testcase.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c    (revision 229404)
--- gcc/fold-const.c    (working copy)
*************** fold_plusminus_mult_expr (location_t loc
*** 6976,6989 ****
        }
      }
  
!   if (same)
      return fold_build2_loc (loc, MULT_EXPR, type,
                        fold_build2_loc (loc, code, type,
                                     fold_convert_loc (loc, type, alt0),
                                     fold_convert_loc (loc, type, alt1)),
                        fold_convert_loc (loc, type, same));
  
!   return NULL_TREE;
  }
  
  /* Subroutine of native_encode_expr.  Encode the INTEGER_CST
--- 6989,7016 ----
        }
      }
  
!   if (!same)
!     return NULL_TREE;
! 
!   if (! INTEGRAL_TYPE_P (type)
!       || TYPE_OVERFLOW_WRAPS (type)
!       || TREE_CODE (same) == INTEGER_CST)
      return fold_build2_loc (loc, MULT_EXPR, type,
                        fold_build2_loc (loc, code, type,
                                     fold_convert_loc (loc, type, alt0),
                                     fold_convert_loc (loc, type, alt1)),
                        fold_convert_loc (loc, type, same));
  
!   /* Same may be zero and thus the operation 'code' may overflow.  Perform
!      the addition in an unsigned type.  */
!   tree utype = unsigned_type_for ( type);
!   return fold_build2_loc (loc, MULT_EXPR, type,
!                         fold_convert_loc
!                           (loc, type,
!                            fold_build2_loc (loc, code, utype,
!                                         fold_convert_loc (loc, utype, alt0),
!                                         fold_convert_loc (loc, utype, alt1))),
!                         fold_convert_loc (loc, type, same));
  }
  
  /* Subroutine of native_encode_expr.  Encode the INTEGER_CST
Index: gcc/testsuite/c-c++-common/ubsan/pr66313.c
===================================================================
*** gcc/testsuite/c-c++-common/ubsan/pr66313.c  (revision 0)
--- gcc/testsuite/c-c++-common/ubsan/pr66313.c  (working copy)
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do run } */
+ /* { dg-options "-fsanitize=undefined -fsanitize-undefined-trap-on-error" } */
+ 
+ int __attribute__((noinline,noclone))
+ f(int a, int b, int c)
+ {
+   return a * b + a * c;
+ }
+ int main()
+ {
+   return f(0, __INT_MAX__, __INT_MAX__);
+ }

Reply via email to