diff options
author | Marek Polacek <mpolacek@gcc.gnu.org> | 2014-06-20 21:20:51 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2014-06-20 21:20:51 +0000 |
commit | 0e37a2f33da9dcc33921ded88f700c28dff7960e (patch) | |
tree | 909724d7e8bcbb98c38c8f42a5f641e17c4ac7ee /gcc/c-family/c-gimplify.c | |
parent | 87681fb55051518fb40426e61ee4fbc2a47073c3 (diff) | |
download | gcc-0e37a2f33da9dcc33921ded88f700c28dff7960e.zip gcc-0e37a2f33da9dcc33921ded88f700c28dff7960e.tar.gz gcc-0e37a2f33da9dcc33921ded88f700c28dff7960e.tar.bz2 |
asan.c (pass_sanopt::execute): Handle IFN_UBSAN_BOUNDS.
* asan.c (pass_sanopt::execute): Handle IFN_UBSAN_BOUNDS.
* flag-types.h (enum sanitize_code): Add SANITIZE_BOUNDS and or it
into SANITIZE_UNDEFINED.
* doc/invoke.texi: Describe -fsanitize=bounds.
* gimplify.c (gimplify_call_expr): Add gimplification of internal
functions created in the FEs.
* internal-fn.c: Move "internal-fn.h" after "tree.h".
(expand_UBSAN_BOUNDS): New function.
* internal-fn.def (UBSAN_BOUNDS): New internal function.
* internal-fn.h: Don't define internal functions here.
* opts.c (common_handle_option): Add -fsanitize=bounds.
* sanitizer.def (BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS,
BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT): Add.
* tree-core.h: Define internal functions here.
(struct tree_base): Add ifn field.
* tree-pretty-print.c: Include "internal-fn.h".
(dump_generic_node): Handle functions without CALL_EXPR_FN.
* tree.c (get_callee_fndecl): Likewise.
(build_call_expr_internal_loc): New function.
* tree.def (CALL_EXPR): Update description.
* tree.h (CALL_EXPR_IFN): Define.
(build_call_expr_internal_loc): Declare.
* ubsan.c (get_ubsan_type_info_for_type): Return 0 for non-arithmetic
types.
(ubsan_type_descriptor): Change bool parameter to enum
ubsan_print_style. Adjust the code. Add handling of
UBSAN_PRINT_ARRAY.
(ubsan_expand_bounds_ifn): New function.
(ubsan_expand_null_ifn): Adjust ubsan_type_descriptor call.
(ubsan_build_overflow_builtin): Likewise.
(instrument_bool_enum_load): Likewise.
(ubsan_instrument_float_cast): Likewise.
* ubsan.h (enum ubsan_print_style): New enum.
(ubsan_expand_bounds_ifn): Declare.
(ubsan_type_descriptor): Adjust declaration. Use a default parameter.
c-family/
* c-gimplify.c: Include "c-ubsan.h" and "pointer-set.h".
(ubsan_walk_array_refs_r): New function.
(c_genericize): Instrument array bounds.
* c-ubsan.c: Include "internal-fn.h".
(ubsan_instrument_division): Mark instrumented arrays as having
side effects. Adjust ubsan_type_descriptor call.
(ubsan_instrument_shift): Likewise.
(ubsan_instrument_vla): Adjust ubsan_type_descriptor call.
(ubsan_instrument_bounds): New function.
(ubsan_array_ref_instrumented_p): New function.
(ubsan_maybe_instrument_array_ref): New function.
* c-ubsan.h (ubsan_instrument_bounds): Declare.
(ubsan_array_ref_instrumented_p): Declare.
(ubsan_maybe_instrument_array_ref): Declare.
testsuite/
* c-c++-common/ubsan/bounds-1.c: New test.
* c-c++-common/ubsan/bounds-2.c: New test.
* c-c++-common/ubsan/bounds-3.c: New test.
* c-c++-common/ubsan/bounds-4.c: New test.
* c-c++-common/ubsan/bounds-5.c: New test.
* c-c++-common/ubsan/bounds-6.c: New test.
From-SVN: r211859
Diffstat (limited to 'gcc/c-family/c-gimplify.c')
-rw-r--r-- | gcc/c-family/c-gimplify.c | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c index 737be4d..c797d99 100644 --- a/gcc/c-family/c-gimplify.c +++ b/gcc/c-family/c-gimplify.c @@ -45,6 +45,8 @@ along with GCC; see the file COPYING3. If not see #include "c-pretty-print.h" #include "cgraph.h" #include "cilk.h" +#include "c-ubsan.h" +#include "pointer-set.h" /* The gimplification pass converts the language-dependent trees (ld-trees) emitted by the parser into language-independent trees @@ -67,6 +69,39 @@ along with GCC; see the file COPYING3. If not see walk back up, we check that they fit our constraints, and copy them into temporaries if not. */ +/* Callback for c_genericize. */ + +static tree +ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data) +{ + struct pointer_set_t *pset = (struct pointer_set_t *) data; + + /* Since walk_tree doesn't call the callback function on the decls + in BIND_EXPR_VARS, we have to walk them manually. */ + if (TREE_CODE (*tp) == BIND_EXPR) + { + for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl)) + { + if (TREE_STATIC (decl)) + { + *walk_subtrees = 0; + continue; + } + walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset, + pset); + walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset); + walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset, + pset); + } + } + else if (TREE_CODE (*tp) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (*tp, 0)) == ARRAY_REF) + ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), true); + else if (TREE_CODE (*tp) == ARRAY_REF) + ubsan_maybe_instrument_array_ref (tp, false); + return NULL_TREE; +} + /* Gimplification of statement trees. */ /* Convert the tree representation of FNDECL from C frontend trees to @@ -79,6 +114,14 @@ c_genericize (tree fndecl) int local_dump_flags; struct cgraph_node *cgn; + if (flag_sanitize & SANITIZE_BOUNDS) + { + struct pointer_set_t *pset = pointer_set_create (); + walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, pset, + pset); + pointer_set_destroy (pset); + } + /* Dump the C-specific tree IR. */ dump_orig = dump_begin (TDI_original, &local_dump_flags); if (dump_orig) @@ -207,16 +250,16 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, } break; } - + case CILK_SPAWN_STMT: - gcc_assert - (fn_contains_cilk_spawn_p (cfun) + gcc_assert + (fn_contains_cilk_spawn_p (cfun) && cilk_detect_spawn_and_unwrap (expr_p)); - + /* If errors are seen, then just process it as a CALL_EXPR. */ if (!seen_error ()) return (enum gimplify_status) gimplify_cilk_spawn (expr_p); - + case MODIFY_EXPR: case INIT_EXPR: case CALL_EXPR: |