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__); + }