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
* tree-inline.c (redirect_all_calls): During inlining
clean up EH stmts and EH edges if redirect_call_stmt_to_callee
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.
2015-01-05 Marek Polacek <polacek@redhat.com>
&& !lookup_attribute ("no_sanitize_undefined",
DECL_ATTRIBUTES (current_function_decl)))
{
- expr = c_save_expr (expr);
- tree check = ubsan_instrument_float_cast (loc, type, expr);
+ tree arg;
+ 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);
if (check == NULL)
return expr;
{
tree ret;
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;
ret = convert_and_check (expr_loc != UNKNOWN_LOCATION
? 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;
}
save = in_late_binary_op;
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;
inner = t = convert (TREE_TYPE (res), t);
in_late_binary_op = save;
DECL_ATTRIBUTES (current_function_decl)))
{
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);
if (check == NULL)
return expr;
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
* gcc.dg/pr64465.c: New test.
--- /dev/null
+/* PR sanitizer/64344 */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=float-cast-overflow" } */
+
+int
+foo (float x)
+{
+ return __builtin_log ((double ) x);
+}
--- /dev/null
+/* 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;
+}
}
/* 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
-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 t, tt, fn, min, max;
else
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)
fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
else
fn = builtin_decl_explicit (bcode);
fn = build_call_expr_loc (loc, fn, 2,
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);
- 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);
+ return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
}
/* Instrument values passed to function arguments with nonnull attribute. */
extern tree ubsan_encode_value (tree, bool = false);
extern bool is_ubsan_builtin_p (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);
#endif /* GCC_UBSAN_H */