Commit e5341100 by Jakub Jelinek Committed by Jakub Jelinek

re PR sanitizer/64344 ([UBSAN] ICE with -fsanitize=float-cast-overflow [ICE in…

re PR sanitizer/64344 ([UBSAN] ICE with -fsanitize=float-cast-overflow [ICE in -fsanitize=float-cast-overflow])

	PR sanitizer/64344
	* ubsan.h (ubsan_instrument_float_cast): Add ARG argument.
	* ubsan.c (ubsan_instrument_float_cast): Add ARG argument, pass
	it to libubsan handler instead of EXPR.  Fold comparisons earlier,
	if the result is integer_zerop, return NULL_TREE.
	* convert.c (convert_to_integer): Pass expr as ARG.
c/
	* c-typeck.c (convert_for_assignment, c_finish_return): For
	-fsanitize=float-cast-overflow casts from REAL_TYPE to integer/enum
	types also set in_late_binary_op around convert call.
	* c-convert.c (convert): For -fsanitize=float-cast-overflow REAL_TYPE
	to integral type casts, if not in_late_binary_op, pass c_fully_fold
	result on expr as last argument to ubsan_instrument_float_cast,
	if in_late_binary_op, don't use c_save_expr but save_expr.
testsuite/
	* c-c++-common/ubsan/pr64344-1.c: New test.
	* c-c++-common/ubsan/pr64344-2.c: New test.

From-SVN: r219201
parent 15aed8c4
2015-01-05 Jakub Jelinek <jakub@redhat.com> 2015-01-05 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/64344
* ubsan.h (ubsan_instrument_float_cast): Add ARG argument.
* ubsan.c (ubsan_instrument_float_cast): Add ARG argument, pass
it to libubsan handler instead of EXPR. Fold comparisons earlier,
if the result is integer_zerop, return NULL_TREE.
* convert.c (convert_to_integer): Pass expr as ARG.
PR tree-optimization/64465 PR tree-optimization/64465
* tree-inline.c (redirect_all_calls): During inlining * tree-inline.c (redirect_all_calls): During inlining
clean up EH stmts and EH edges if redirect_call_stmt_to_callee clean up EH stmts and EH edges if redirect_call_stmt_to_callee
......
2015-01-05 Jakub Jelinek <jakub@redhat.com> 2015-01-05 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/64344
* c-typeck.c (convert_for_assignment, c_finish_return): For
-fsanitize=float-cast-overflow casts from REAL_TYPE to integer/enum
types also set in_late_binary_op around convert call.
* c-convert.c (convert): For -fsanitize=float-cast-overflow REAL_TYPE
to integral type casts, if not in_late_binary_op, pass c_fully_fold
result on expr as last argument to ubsan_instrument_float_cast,
if in_late_binary_op, don't use c_save_expr but save_expr.
Update copyright years. Update copyright years.
2015-01-05 Marek Polacek <polacek@redhat.com> 2015-01-05 Marek Polacek <polacek@redhat.com>
......
...@@ -117,8 +117,18 @@ convert (tree type, tree expr) ...@@ -117,8 +117,18 @@ convert (tree type, tree expr)
&& !lookup_attribute ("no_sanitize_undefined", && !lookup_attribute ("no_sanitize_undefined",
DECL_ATTRIBUTES (current_function_decl))) DECL_ATTRIBUTES (current_function_decl)))
{ {
expr = c_save_expr (expr); tree arg;
tree check = ubsan_instrument_float_cast (loc, type, expr); if (in_late_binary_op)
{
expr = save_expr (expr);
arg = expr;
}
else
{
expr = c_save_expr (expr);
arg = c_fully_fold (expr, false, NULL);
}
tree check = ubsan_instrument_float_cast (loc, type, expr, arg);
expr = fold_build1 (FIX_TRUNC_EXPR, type, expr); expr = fold_build1 (FIX_TRUNC_EXPR, type, expr);
if (check == NULL) if (check == NULL)
return expr; return expr;
......
...@@ -5885,12 +5885,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, ...@@ -5885,12 +5885,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
{ {
tree ret; tree ret;
bool save = in_late_binary_op; bool save = in_late_binary_op;
if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE) if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE
|| (coder == REAL_TYPE
&& (codel == INTEGER_TYPE || codel == ENUMERAL_TYPE)
&& (flag_sanitize & SANITIZE_FLOAT_CAST)))
in_late_binary_op = true; in_late_binary_op = true;
ret = convert_and_check (expr_loc != UNKNOWN_LOCATION ret = convert_and_check (expr_loc != UNKNOWN_LOCATION
? expr_loc : location, type, orig_rhs); ? expr_loc : location, type, orig_rhs);
if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE) in_late_binary_op = save;
in_late_binary_op = save;
return ret; return ret;
} }
...@@ -9369,7 +9371,11 @@ c_finish_return (location_t loc, tree retval, tree origtype) ...@@ -9369,7 +9371,11 @@ c_finish_return (location_t loc, tree retval, tree origtype)
save = in_late_binary_op; save = in_late_binary_op;
if (TREE_CODE (TREE_TYPE (res)) == BOOLEAN_TYPE if (TREE_CODE (TREE_TYPE (res)) == BOOLEAN_TYPE
|| TREE_CODE (TREE_TYPE (res)) == COMPLEX_TYPE) || TREE_CODE (TREE_TYPE (res)) == COMPLEX_TYPE
|| (TREE_CODE (TREE_TYPE (t)) == REAL_TYPE
&& (TREE_CODE (TREE_TYPE (res)) == INTEGER_TYPE
|| TREE_CODE (TREE_TYPE (res)) == ENUMERAL_TYPE)
&& (flag_sanitize & SANITIZE_FLOAT_CAST)))
in_late_binary_op = true; in_late_binary_op = true;
inner = t = convert (TREE_TYPE (res), t); inner = t = convert (TREE_TYPE (res), t);
in_late_binary_op = save; in_late_binary_op = save;
......
...@@ -890,7 +890,7 @@ convert_to_integer (tree type, tree expr) ...@@ -890,7 +890,7 @@ convert_to_integer (tree type, tree expr)
DECL_ATTRIBUTES (current_function_decl))) DECL_ATTRIBUTES (current_function_decl)))
{ {
expr = save_expr (expr); expr = save_expr (expr);
tree check = ubsan_instrument_float_cast (loc, type, expr); tree check = ubsan_instrument_float_cast (loc, type, expr, expr);
expr = build1 (FIX_TRUNC_EXPR, type, expr); expr = build1 (FIX_TRUNC_EXPR, type, expr);
if (check == NULL) if (check == NULL)
return expr; return expr;
......
2015-01-05 Jakub Jelinek <jakub@redhat.com> 2015-01-05 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/64344
* c-c++-common/ubsan/pr64344-1.c: New test.
* c-c++-common/ubsan/pr64344-2.c: New test.
PR tree-optimization/64465 PR tree-optimization/64465
* gcc.dg/pr64465.c: New test. * gcc.dg/pr64465.c: New test.
......
/* PR sanitizer/64344 */
/* { dg-do compile } */
/* { dg-options "-fsanitize=float-cast-overflow" } */
int
foo (float x)
{
return __builtin_log ((double ) x);
}
/* PR sanitizer/64344 */
/* { dg-do compile } */
/* { dg-options "-fsanitize=float-cast-overflow" } */
int
foo (void)
{
static const int a = 0.5;
static const int b = (int) 13.5 + 1;
return a + b;
}
...@@ -1252,10 +1252,11 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi) ...@@ -1252,10 +1252,11 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
} }
/* Instrument float point-to-integer conversion. TYPE is an integer type of /* Instrument float point-to-integer conversion. TYPE is an integer type of
destination, EXPR is floating-point expression. */ destination, EXPR is floating-point expression. ARG is what to pass
the libubsan call as value, often EXPR itself. */
tree tree
ubsan_instrument_float_cast (location_t loc, tree type, tree expr) ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
{ {
tree expr_type = TREE_TYPE (expr); tree expr_type = TREE_TYPE (expr);
tree t, tt, fn, min, max; tree t, tt, fn, min, max;
...@@ -1348,6 +1349,12 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr) ...@@ -1348,6 +1349,12 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
else else
return NULL_TREE; return NULL_TREE;
t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
if (integer_zerop (t))
return NULL_TREE;
if (flag_sanitize_undefined_trap_on_error) if (flag_sanitize_undefined_trap_on_error)
fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
else else
...@@ -1364,14 +1371,10 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr) ...@@ -1364,14 +1371,10 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
fn = builtin_decl_explicit (bcode); fn = builtin_decl_explicit (bcode);
fn = build_call_expr_loc (loc, fn, 2, fn = build_call_expr_loc (loc, fn, 2,
build_fold_addr_expr_loc (loc, data), build_fold_addr_expr_loc (loc, data),
ubsan_encode_value (expr, false)); ubsan_encode_value (arg, false));
} }
t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min); return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
return fold_build3 (COND_EXPR, void_type_node,
fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt),
fn, integer_zero_node);
} }
/* Instrument values passed to function arguments with nonnull attribute. */ /* Instrument values passed to function arguments with nonnull attribute. */
......
...@@ -47,7 +47,7 @@ extern tree ubsan_type_descriptor (tree, enum ubsan_print_style = UBSAN_PRINT_NO ...@@ -47,7 +47,7 @@ extern tree ubsan_type_descriptor (tree, enum ubsan_print_style = UBSAN_PRINT_NO
extern tree ubsan_encode_value (tree, bool = false); extern tree ubsan_encode_value (tree, bool = false);
extern bool is_ubsan_builtin_p (tree); extern bool is_ubsan_builtin_p (tree);
extern tree ubsan_build_overflow_builtin (tree_code, location_t, tree, tree, tree); extern tree ubsan_build_overflow_builtin (tree_code, location_t, tree, tree, tree);
extern tree ubsan_instrument_float_cast (location_t, tree, tree); extern tree ubsan_instrument_float_cast (location_t, tree, tree, tree);
extern tree ubsan_get_source_location_type (void); extern tree ubsan_get_source_location_type (void);
#endif /* GCC_UBSAN_H */ #endif /* GCC_UBSAN_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment