* [PATCH] ASAN: handle addressable params (PR sanitize/81040). @ 2017-06-19 13:50 Martin Liška 2017-06-19 14:13 ` Jakub Jelinek 0 siblings, 1 reply; 13+ messages in thread From: Martin Liška @ 2017-06-19 13:50 UTC (permalink / raw) To: GCC Patches; +Cc: Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 445 bytes --] Hi. Following patch addresses issue where we have a function argument which address is taken and -fsanitize=address does not wrap up the argument with red zone. It's done in sanopt pass, where I create a new automatic variable which is used in the function instead of the original argument. Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. And I can bootstrap-asan on the same machine. Ready to be installed? Martin [-- Attachment #2: 0001-ASAN-handle-addressable-params-PR-sanitize-81040.patch --] [-- Type: text/x-patch, Size: 7939 bytes --] From f8a48a3f361d9914dd45c1896e8c5ba607a62b06 Mon Sep 17 00:00:00 2001 From: marxin <mliska@suse.cz> Date: Wed, 14 Jun 2017 11:40:01 +0200 Subject: [PATCH] ASAN: handle addressable params (PR sanitize/81040). gcc/testsuite/ChangeLog: 2017-06-19 Martin Liska <mliska@suse.cz> PR sanitize/81040 * g++.dg/asan/function-argument-1.C: New test. * g++.dg/asan/function-argument-2.C: New test. * g++.dg/asan/function-argument-3.C: New test. gcc/ChangeLog: 2017-06-19 Martin Liska <mliska@suse.cz> PR sanitize/81040 * sanopt.c (rewrite_usage_of_param): New function. (sanitize_rewrite_addressable_params): Likewise. (pass_sanopt::execute): Call rewrite_usage_of_param. --- gcc/sanopt.c | 118 ++++++++++++++++++++++++ gcc/testsuite/g++.dg/asan/function-argument-1.C | 30 ++++++ gcc/testsuite/g++.dg/asan/function-argument-2.C | 24 +++++ gcc/testsuite/g++.dg/asan/function-argument-3.C | 27 ++++++ 4 files changed, 199 insertions(+) create mode 100644 gcc/testsuite/g++.dg/asan/function-argument-1.C create mode 100644 gcc/testsuite/g++.dg/asan/function-argument-2.C create mode 100644 gcc/testsuite/g++.dg/asan/function-argument-3.C diff --git a/gcc/sanopt.c b/gcc/sanopt.c index 16bdba76042..10464841972 100644 --- a/gcc/sanopt.c +++ b/gcc/sanopt.c @@ -37,6 +37,10 @@ along with GCC; see the file COPYING3. If not see #include "gimple-ssa.h" #include "tree-phinodes.h" #include "ssa-iterators.h" +#include "gimplify.h" +#include "gimple-iterator.h" +#include "gimple-walk.h" +#include "cfghooks.h" /* This is used to carry information about basic blocks. It is attached to the AUX field of the standard CFG block. */ @@ -858,6 +862,117 @@ sanitize_asan_mark_poison (void) } } +static tree +rewrite_usage_of_param (tree *op, int *walk_subtrees, void *data) +{ + struct walk_stmt_info *wi = (struct walk_stmt_info *) data; + std::pair<tree, tree> *replacement = (std::pair<tree, tree> *)wi->info; + + if (*op == replacement->first) + { + *op = replacement->second; + *walk_subtrees = 0; + } + + return NULL; +} + +/* For a given function FUN, rewrite all addressable parameters so that + a new automatic variable is introduced. Right after function entry + a parameter is assigned to the variable. */ + +static void +sanitize_rewrite_addressable_params (function *fun) +{ + basic_block entry_bb = NULL; + + for (tree arg = DECL_ARGUMENTS (current_function_decl); + arg; arg = DECL_CHAIN (arg)) + { + if (TREE_ADDRESSABLE (arg) && !TREE_ADDRESSABLE (TREE_TYPE (arg))) + { + /* The parameter is no longer addressable. */ + tree type = TREE_TYPE (arg); + TREE_ADDRESSABLE (arg) = 0; + + /* Create a new automatic variable. */ + tree var = build_decl (DECL_SOURCE_LOCATION (arg), + VAR_DECL, DECL_NAME (arg), type); + TREE_ADDRESSABLE (var) = 1; + DECL_ARTIFICIAL (var) = 1; + DECL_SEEN_IN_BIND_EXPR_P (var) = 0; + + gimple_add_tmp_var (var); + + if (dump_file) + fprintf (dump_file, + "Rewritting parameter whos address is taken: %s\n", + IDENTIFIER_POINTER (DECL_NAME (arg))); + + gimple_seq stmts = NULL; + + /* Assign value of parameter to newly created variable. */ + if ((TREE_CODE (type) == COMPLEX_TYPE + || TREE_CODE (type) == VECTOR_TYPE)) + { + /* We need to create a SSA name that will be used for the + assignment. */ + tree tmp = make_ssa_name (type); + gimple *g = gimple_build_assign (tmp, arg); + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); + gimple_seq_add_stmt (&stmts, g); + g = gimple_build_assign (var, tmp); + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); + gimple_seq_add_stmt (&stmts, g); + } + else + { + gimple *g = gimple_build_assign (var, arg); + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); + gimple_seq_add_stmt (&stmts, g); + } + + /* Replace all usages of PARM_DECL with the newly + created variable VAR. */ + basic_block bb; + gimple_stmt_iterator gsi; + FOR_EACH_BB_FN (bb, fun) + { + std::pair<tree, tree> replacement (arg, var); + struct walk_stmt_info wi; + memset (&wi, 0, sizeof (wi)); + wi.info = (void *)&replacement; + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + gimple_stmt_iterator it = gsi_for_stmt (stmt); + walk_gimple_stmt (&it, NULL, rewrite_usage_of_param, &wi); + } + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gphi *phi = dyn_cast<gphi *> (gsi_stmt (gsi)); + for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) + { + hash_set<tree> visited_nodes; + walk_tree (gimple_phi_arg_def_ptr (phi, i), + rewrite_usage_of_param, &wi, &visited_nodes); + } + } + } + + if (entry_bb == NULL) + { + entry_bb = ENTRY_BLOCK_PTR_FOR_FN (fun); + entry_bb = split_edge (single_succ_edge (entry_bb)); + } + + gimple_stmt_iterator gsi2 = gsi_start_bb (entry_bb); + gsi_insert_seq_before (&gsi2, stmts, GSI_NEW_STMT); + } + } +} + unsigned int pass_sanopt::execute (function *fun) { @@ -891,6 +1006,9 @@ pass_sanopt::execute (function *fun) sanitize_asan_mark_poison (); } + if (asan_sanitize_stack_p ()) + sanitize_rewrite_addressable_params (fun); + bool use_calls = ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD < INT_MAX && asan_num_accesses >= ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD; diff --git a/gcc/testsuite/g++.dg/asan/function-argument-1.C b/gcc/testsuite/g++.dg/asan/function-argument-1.C new file mode 100644 index 00000000000..148c4628316 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/function-argument-1.C @@ -0,0 +1,30 @@ +// { dg-do run } +// { dg-shouldfail "asan" } + +struct A +{ + int a[5]; +}; + +static __attribute__ ((noinline)) int +goo (A *a) +{ + int *ptr = &a->a[0]; + return *(volatile int *) (ptr - 1); +} + +__attribute__ ((noinline)) int +foo (A arg) +{ + return goo (&arg); +} + +int +main () +{ + return foo (A ()); +} + +// { dg-output "ERROR: AddressSanitizer: stack-buffer-underflow on address.*(\n|\r\n|\r)" } +// { dg-output "READ of size . at.*" } +// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* underflows this variable.*" } diff --git a/gcc/testsuite/g++.dg/asan/function-argument-2.C b/gcc/testsuite/g++.dg/asan/function-argument-2.C new file mode 100644 index 00000000000..3a7c33bdaaa --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/function-argument-2.C @@ -0,0 +1,24 @@ +// { dg-do run } +// { dg-shouldfail "asan" } + +static __attribute__ ((noinline)) int +goo (int *a) +{ + return *(volatile int *)a; +} + +__attribute__ ((noinline)) int +foo (char arg) +{ + return goo ((int *)&arg); +} + +int +main () +{ + return foo (12); +} + +// { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow on address.*(\n|\r\n|\r)" } +// { dg-output "READ of size . at.*" } +// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* partially overflows this variable.*" } diff --git a/gcc/testsuite/g++.dg/asan/function-argument-3.C b/gcc/testsuite/g++.dg/asan/function-argument-3.C new file mode 100644 index 00000000000..14617ba8425 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/function-argument-3.C @@ -0,0 +1,27 @@ +// { dg-do run } +// { dg-shouldfail "asan" } + +typedef int v4si __attribute__ ((vector_size (16))); + +static __attribute__ ((noinline)) int +goo (v4si *a) +{ + return (*(volatile v4si *) (a + 1))[2]; +} + +__attribute__ ((noinline)) int +foo (v4si arg) +{ + return goo (&arg); +} + +int +main () +{ + v4si v = {1,2,3,4}; + return foo (v); +} + +// { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow on address.*(\n|\r\n|\r)" } +// { dg-output "READ of size . at.*" } +// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* overflows this variable.*" } -- 2.13.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] ASAN: handle addressable params (PR sanitize/81040). 2017-06-19 13:50 [PATCH] ASAN: handle addressable params (PR sanitize/81040) Martin Liška @ 2017-06-19 14:13 ` Jakub Jelinek 2017-06-20 9:23 ` Martin Liška 0 siblings, 1 reply; 13+ messages in thread From: Jakub Jelinek @ 2017-06-19 14:13 UTC (permalink / raw) To: Martin Liška; +Cc: GCC Patches On Mon, Jun 19, 2017 at 03:50:42PM +0200, Martin LiÅ¡ka wrote: > @@ -858,6 +862,117 @@ sanitize_asan_mark_poison (void) > } > } > Missing function comment. > +static tree > +rewrite_usage_of_param (tree *op, int *walk_subtrees, void *data) > +{ > + struct walk_stmt_info *wi = (struct walk_stmt_info *) data; > + std::pair<tree, tree> *replacement = (std::pair<tree, tree> *)wi->info; Missing space after ) > + > + if (*op == replacement->first) > + { > + *op = replacement->second; > + *walk_subtrees = 0; > + } > + > + return NULL; > +} > +static void > +sanitize_rewrite_addressable_params (function *fun) > +{ > + basic_block entry_bb = NULL; > + > + for (tree arg = DECL_ARGUMENTS (current_function_decl); > + arg; arg = DECL_CHAIN (arg)) > + { > + if (TREE_ADDRESSABLE (arg) && !TREE_ADDRESSABLE (TREE_TYPE (arg))) > + { > + /* The parameter is no longer addressable. */ > + tree type = TREE_TYPE (arg); > + TREE_ADDRESSABLE (arg) = 0; > + > + /* Create a new automatic variable. */ > + tree var = build_decl (DECL_SOURCE_LOCATION (arg), > + VAR_DECL, DECL_NAME (arg), type); > + TREE_ADDRESSABLE (var) = 1; > + DECL_ARTIFICIAL (var) = 1; > + DECL_SEEN_IN_BIND_EXPR_P (var) = 0; I think it is highly inefficient to walk the whole IL for every addressable argument. Can't you first find out what PARM_DECLs you need to change, stick the corresponding VAR_DECL somewhere (dunno, e.g. a vector with pairs perhaps sorted by DECL_UID, or stick it into DECL_VALUE_EXPR or whatever), then if you create at least one, walk whole IL and replace all the PARM_DECLs you want to replace, then finally clear the TREE_ADDRESSABLE flag for all of them and emit the initialization sequence? Then something needs to be done for debugging too. If it is without VTA, then probably just having DECL_VALUE_EXPR is good enough, otherwise (VTA) you probably don't want that (or can reset it at that point), but instead emit after the initialization stmt a debug stmt that the variable value now lives in a different var. Though ideally we want the debugger to be able to also change the value of the var, that might be harder. With DECL_VALUE_EXPR on the other side the debug info will be incorrect in the prologue until it is assigned to the slot. > + > + gimple_add_tmp_var (var); > + > + if (dump_file) > + fprintf (dump_file, > + "Rewritting parameter whos address is taken: %s\n", > + IDENTIFIER_POINTER (DECL_NAME (arg))); s/tting/ting/, s/whos/whose/ > + > + gimple_seq stmts = NULL; > + > + /* Assign value of parameter to newly created variable. */ > + if ((TREE_CODE (type) == COMPLEX_TYPE > + || TREE_CODE (type) == VECTOR_TYPE)) > + { > + /* We need to create a SSA name that will be used for the > + assignment. */ > + tree tmp = make_ssa_name (type); > + gimple *g = gimple_build_assign (tmp, arg); > + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); > + gimple_seq_add_stmt (&stmts, g); > + g = gimple_build_assign (var, tmp); > + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); > + gimple_seq_add_stmt (&stmts, g); > + } > + else > + { > + gimple *g = gimple_build_assign (var, arg); > + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); > + gimple_seq_add_stmt (&stmts, g); > + } I don't understand the distinction. If you turn the original parm for complex/vector DECL_GIMPLE_REG_P, you should need the exact same code (but I think it would be better to use the default SSA_NAME of the PARM_DECL if it is a gimple reg type, rather than use the PARM_DECL itself and wait for update_ssa). Jakub ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] ASAN: handle addressable params (PR sanitize/81040). 2017-06-19 14:13 ` Jakub Jelinek @ 2017-06-20 9:23 ` Martin Liška 2017-06-20 9:32 ` Jakub Jelinek 0 siblings, 1 reply; 13+ messages in thread From: Martin Liška @ 2017-06-20 9:23 UTC (permalink / raw) To: Jakub Jelinek; +Cc: GCC Patches On 06/19/2017 04:13 PM, Jakub Jelinek wrote: > On Mon, Jun 19, 2017 at 03:50:42PM +0200, Martin LiÅ¡ka wrote: >> @@ -858,6 +862,117 @@ sanitize_asan_mark_poison (void) >> } >> } >> > > Missing function comment. > >> +static tree >> +rewrite_usage_of_param (tree *op, int *walk_subtrees, void *data) >> +{ >> + struct walk_stmt_info *wi = (struct walk_stmt_info *) data; >> + std::pair<tree, tree> *replacement = (std::pair<tree, tree> *)wi->info; > > Missing space after ) > >> + >> + if (*op == replacement->first) >> + { >> + *op = replacement->second; >> + *walk_subtrees = 0; >> + } >> + >> + return NULL; >> +} > >> +static void >> +sanitize_rewrite_addressable_params (function *fun) >> +{ >> + basic_block entry_bb = NULL; >> + >> + for (tree arg = DECL_ARGUMENTS (current_function_decl); >> + arg; arg = DECL_CHAIN (arg)) >> + { >> + if (TREE_ADDRESSABLE (arg) && !TREE_ADDRESSABLE (TREE_TYPE (arg))) >> + { >> + /* The parameter is no longer addressable. */ >> + tree type = TREE_TYPE (arg); >> + TREE_ADDRESSABLE (arg) = 0; >> + >> + /* Create a new automatic variable. */ >> + tree var = build_decl (DECL_SOURCE_LOCATION (arg), >> + VAR_DECL, DECL_NAME (arg), type); >> + TREE_ADDRESSABLE (var) = 1; >> + DECL_ARTIFICIAL (var) = 1; >> + DECL_SEEN_IN_BIND_EXPR_P (var) = 0; > > I think it is highly inefficient to walk the whole IL for every addressable > argument. Can't you first find out what PARM_DECLs you need to change, > stick the corresponding VAR_DECL somewhere (dunno, e.g. a vector with pairs > perhaps sorted by DECL_UID, or stick it into DECL_VALUE_EXPR or whatever), > then if you create at least one, walk whole IL and replace all the > PARM_DECLs you want to replace, then finally clear the TREE_ADDRESSABLE > flag for all of them and emit the initialization sequence? Yes, this is doable. I've done that. > Then something needs to be done for debugging too. If it is without VTA, > then probably just having DECL_VALUE_EXPR is good enough, otherwise > (VTA) you probably don't want that (or can reset it at that point), but > instead emit after the initialization stmt a debug stmt that the variable > value now lives in a different var. Though ideally we want the debugger > to be able to also change the value of the var, that might be harder. > With DECL_VALUE_EXPR on the other side the debug info will be incorrect in > the prologue until it is assigned to the slot. Here I'm not sure about how to distinguish whether to build or not to build the debug statement. According to flag_var_tracking? You mean something like: g = gimple_build_debug_bind (arg, var, g); ? > >> + >> + gimple_add_tmp_var (var); >> + >> + if (dump_file) >> + fprintf (dump_file, >> + "Rewritting parameter whos address is taken: %s\n", >> + IDENTIFIER_POINTER (DECL_NAME (arg))); > > s/tting/ting/, s/whos/whose/ >> + >> + gimple_seq stmts = NULL; >> + >> + /* Assign value of parameter to newly created variable. */ >> + if ((TREE_CODE (type) == COMPLEX_TYPE >> + || TREE_CODE (type) == VECTOR_TYPE)) >> + { >> + /* We need to create a SSA name that will be used for the >> + assignment. */ >> + tree tmp = make_ssa_name (type); >> + gimple *g = gimple_build_assign (tmp, arg); >> + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); >> + gimple_seq_add_stmt (&stmts, g); >> + g = gimple_build_assign (var, tmp); >> + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); >> + gimple_seq_add_stmt (&stmts, g); >> + } >> + else >> + { >> + gimple *g = gimple_build_assign (var, arg); >> + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); >> + gimple_seq_add_stmt (&stmts, g); >> + } > > I don't understand the distinction. If you turn the original parm > for complex/vector DECL_GIMPLE_REG_P, you should need the exact same code > (but I think it would be better to use the default SSA_NAME of the PARM_DECL > if it is a gimple reg type, rather than use the PARM_DECL itself > and wait for update_ssa). Yes, the test-case /gcc/testsuite/g++.dg/asan/function-argument-3.C fails for me as one needs to have a temporary SSA name, otherwise: /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/asan/function-argument-3.C:13:1: error: invalid rhs for gimple memory store foo (v4si arg) ^~~ arg arg # .MEM_4 = VDEF <.MEM_1(D)> arg = arg; during GIMPLE pass: sanopt If I see correctly the function in my test-case does not have default def SSA name for the parameter. Thus I guess I need to create a SSA name? Thanks, Martin > > Jakub > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] ASAN: handle addressable params (PR sanitize/81040). 2017-06-20 9:23 ` Martin Liška @ 2017-06-20 9:32 ` Jakub Jelinek 2017-06-20 13:07 ` Martin Liška 0 siblings, 1 reply; 13+ messages in thread From: Jakub Jelinek @ 2017-06-20 9:32 UTC (permalink / raw) To: Martin Liška; +Cc: GCC Patches On Tue, Jun 20, 2017 at 11:23:36AM +0200, Martin LiÅ¡ka wrote: > > Then something needs to be done for debugging too. If it is without VTA, > > then probably just having DECL_VALUE_EXPR is good enough, otherwise > > (VTA) you probably don't want that (or can reset it at that point), but > > instead emit after the initialization stmt a debug stmt that the variable > > value now lives in a different var. Though ideally we want the debugger > > to be able to also change the value of the var, that might be harder. > > With DECL_VALUE_EXPR on the other side the debug info will be incorrect in > > the prologue until it is assigned to the slot. > > Here I'm not sure about how to distinguish whether to build or not to build > the debug statement. According to flag_var_tracking? More like if (target_for_debug_bind (arg)) And if that is false, just make sure DECL_VALUE_EXPR is set to var. > You mean something like: > g = gimple_build_debug_bind (arg, var, g); > ? Well, there is no stmt, so the last argument would be just NULL. > > I don't understand the distinction. If you turn the original parm > > for complex/vector DECL_GIMPLE_REG_P, you should need the exact same code > > (but I think it would be better to use the default SSA_NAME of the PARM_DECL > > if it is a gimple reg type, rather than use the PARM_DECL itself > > and wait for update_ssa). > > Yes, the test-case /gcc/testsuite/g++.dg/asan/function-argument-3.C fails for me > as one needs to have a temporary SSA name, otherwise: > > /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/asan/function-argument-3.C:13:1: error: invalid rhs for gimple memory store > foo (v4si arg) > ^~~ > arg > > arg > > # .MEM_4 = VDEF <.MEM_1(D)> > arg = arg; > during GIMPLE pass: sanopt > > If I see correctly the function in my test-case does not have default def SSA name for the parameter. > Thus I guess I need to create a SSA name? I'd expect if you have DECL_GIMPLE_REG_P set on the PARM_DECL and use the default def, you shouldn't run into this. Jakub ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] ASAN: handle addressable params (PR sanitize/81040). 2017-06-20 9:32 ` Jakub Jelinek @ 2017-06-20 13:07 ` Martin Liška 2017-06-28 13:16 ` Martin Liška 2017-06-29 11:17 ` Jakub Jelinek 0 siblings, 2 replies; 13+ messages in thread From: Martin Liška @ 2017-06-20 13:07 UTC (permalink / raw) To: Jakub Jelinek; +Cc: GCC Patches [-- Attachment #1: Type: text/plain, Size: 2257 bytes --] On 06/20/2017 11:32 AM, Jakub Jelinek wrote: > On Tue, Jun 20, 2017 at 11:23:36AM +0200, Martin LiÅ¡ka wrote: >>> Then something needs to be done for debugging too. If it is without VTA, >>> then probably just having DECL_VALUE_EXPR is good enough, otherwise >>> (VTA) you probably don't want that (or can reset it at that point), but >>> instead emit after the initialization stmt a debug stmt that the variable >>> value now lives in a different var. Though ideally we want the debugger >>> to be able to also change the value of the var, that might be harder. >>> With DECL_VALUE_EXPR on the other side the debug info will be incorrect in >>> the prologue until it is assigned to the slot. >> >> Here I'm not sure about how to distinguish whether to build or not to build >> the debug statement. According to flag_var_tracking? > > More like if (target_for_debug_bind (arg)) > And if that is false, just make sure DECL_VALUE_EXPR is set to var. > >> You mean something like: >> g = gimple_build_debug_bind (arg, var, g); >> ? > > Well, there is no stmt, so the last argument would be just NULL. > >>> I don't understand the distinction. If you turn the original parm >>> for complex/vector DECL_GIMPLE_REG_P, you should need the exact same code >>> (but I think it would be better to use the default SSA_NAME of the PARM_DECL >>> if it is a gimple reg type, rather than use the PARM_DECL itself >>> and wait for update_ssa). >> >> Yes, the test-case /gcc/testsuite/g++.dg/asan/function-argument-3.C fails for me >> as one needs to have a temporary SSA name, otherwise: >> >> /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/asan/function-argument-3.C:13:1: error: invalid rhs for gimple memory store >> foo (v4si arg) >> ^~~ >> arg >> >> arg >> >> # .MEM_4 = VDEF <.MEM_1(D)> >> arg = arg; >> during GIMPLE pass: sanopt >> >> If I see correctly the function in my test-case does not have default def SSA name for the parameter. >> Thus I guess I need to create a SSA name? > > I'd expect if you have DECL_GIMPLE_REG_P set on the PARM_DECL and > use the default def, you shouldn't run into this. > > Jakub > Good I fixed that in v2, that passes regression tests. Ale objections should be resolved in the version. Ready for trunk? Martin [-- Attachment #2: 0001-ASAN-handle-addressable-params-PR-sanitize-81040-v2.patch --] [-- Type: text/x-patch, Size: 8256 bytes --] From ed5da705250c3015e964de8d23d1aa3d0056012a Mon Sep 17 00:00:00 2001 From: marxin <mliska@suse.cz> Date: Wed, 14 Jun 2017 11:40:01 +0200 Subject: [PATCH] ASAN: handle addressable params (PR sanitize/81040). gcc/testsuite/ChangeLog: 2017-06-19 Martin Liska <mliska@suse.cz> PR sanitize/81040 * g++.dg/asan/function-argument-1.C: New test. * g++.dg/asan/function-argument-2.C: New test. * g++.dg/asan/function-argument-3.C: New test. gcc/ChangeLog: 2017-06-19 Martin Liska <mliska@suse.cz> PR sanitize/81040 * sanopt.c (rewrite_usage_of_param): New function. (sanitize_rewrite_addressable_params): Likewise. (pass_sanopt::execute): Call rewrite_usage_of_param. --- gcc/sanopt.c | 132 ++++++++++++++++++++++++ gcc/testsuite/g++.dg/asan/function-argument-1.C | 30 ++++++ gcc/testsuite/g++.dg/asan/function-argument-2.C | 24 +++++ gcc/testsuite/g++.dg/asan/function-argument-3.C | 27 +++++ 4 files changed, 213 insertions(+) create mode 100644 gcc/testsuite/g++.dg/asan/function-argument-1.C create mode 100644 gcc/testsuite/g++.dg/asan/function-argument-2.C create mode 100644 gcc/testsuite/g++.dg/asan/function-argument-3.C diff --git a/gcc/sanopt.c b/gcc/sanopt.c index 16bdba76042..077811b5b93 100644 --- a/gcc/sanopt.c +++ b/gcc/sanopt.c @@ -37,6 +37,12 @@ along with GCC; see the file COPYING3. If not see #include "gimple-ssa.h" #include "tree-phinodes.h" #include "ssa-iterators.h" +#include "gimplify.h" +#include "gimple-iterator.h" +#include "gimple-walk.h" +#include "cfghooks.h" +#include "tree-dfa.h" +#include "tree-ssa.h" /* This is used to carry information about basic blocks. It is attached to the AUX field of the standard CFG block. */ @@ -858,6 +864,129 @@ sanitize_asan_mark_poison (void) } } +/* Rewrite all usages of tree OP which is a PARM_DECL with a VAR_DECL + that is it's DECL_VALUE_EXPR. */ + +static tree +rewrite_usage_of_param (tree *op, int *walk_subtrees, void *) +{ + if (TREE_CODE (*op) == PARM_DECL && DECL_VALUE_EXPR (*op) != NULL_TREE) + { + *op = DECL_VALUE_EXPR (*op); + *walk_subtrees = 0; + } + + return NULL; +} + +/* For a given function FUN, rewrite all addressable parameters so that + a new automatic variable is introduced. Right after function entry + a parameter is assigned to the variable. */ + +static void +sanitize_rewrite_addressable_params (function *fun) +{ + gimple *g; + gimple_seq stmts = NULL; + auto_vec<tree> addressable_params; + + for (tree arg = DECL_ARGUMENTS (current_function_decl); + arg; arg = DECL_CHAIN (arg)) + { + if (TREE_ADDRESSABLE (arg) && !TREE_ADDRESSABLE (TREE_TYPE (arg))) + { + TREE_ADDRESSABLE (arg) = 0; + /* The parameter is no longer addressable. */ + tree type = TREE_TYPE (arg); + addressable_params.safe_push (arg); + + /* Create a new automatic variable. */ + tree var = build_decl (DECL_SOURCE_LOCATION (arg), + VAR_DECL, DECL_NAME (arg), type); + TREE_ADDRESSABLE (var) = 1; + DECL_ARTIFICIAL (var) = 1; + DECL_SEEN_IN_BIND_EXPR_P (var) = 0; + + gimple_add_tmp_var (var); + + if (dump_file) + fprintf (dump_file, + "Rewriting parameter whose address is taken: %s\n", + IDENTIFIER_POINTER (DECL_NAME (arg))); + + SET_DECL_VALUE_EXPR (arg, var); + + /* Assign value of parameter to newly created variable. */ + if ((TREE_CODE (type) == COMPLEX_TYPE + || TREE_CODE (type) == VECTOR_TYPE)) + { + /* We need to create a SSA name that will be used for the + assignment. */ + tree tmp; + if (DECL_GIMPLE_REG_P (arg)) + tmp = ssa_default_def (cfun, arg); + else + { + tmp = make_ssa_name (type); + g = gimple_build_assign (tmp, arg); + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); + gimple_seq_add_stmt (&stmts, g); + } + g = gimple_build_assign (var, tmp); + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); + gimple_seq_add_stmt (&stmts, g); + } + else + { + dump_function (0, cfun->decl); + g = gimple_build_assign (var, arg); + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); + gimple_seq_add_stmt (&stmts, g); + } + + if (target_for_debug_bind (arg)) + { + g = gimple_build_debug_bind (arg, var, NULL); + gimple_seq_add_stmt (&stmts, g); + } + } + } + + if (addressable_params.is_empty ()) + return; + + /* Replace all usages of PARM_DECLs with the newly + created variable VAR. */ + basic_block bb; + FOR_EACH_BB_FN (bb, fun) + { + gimple_stmt_iterator gsi; + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + gimple_stmt_iterator it = gsi_for_stmt (stmt); + walk_gimple_stmt (&it, NULL, rewrite_usage_of_param, NULL); + } + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gphi *phi = dyn_cast<gphi *> (gsi_stmt (gsi)); + for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) + { + hash_set<tree> visited_nodes; + walk_tree (gimple_phi_arg_def_ptr (phi, i), + rewrite_usage_of_param, NULL, &visited_nodes); + } + } + } + + /* Insert default assignments at the beginning of a function. */ + basic_block entry_bb = ENTRY_BLOCK_PTR_FOR_FN (fun); + entry_bb = split_edge (single_succ_edge (entry_bb)); + + gimple_stmt_iterator gsi = gsi_start_bb (entry_bb); + gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT); +} + unsigned int pass_sanopt::execute (function *fun) { @@ -891,6 +1020,9 @@ pass_sanopt::execute (function *fun) sanitize_asan_mark_poison (); } + if (asan_sanitize_stack_p ()) + sanitize_rewrite_addressable_params (fun); + bool use_calls = ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD < INT_MAX && asan_num_accesses >= ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD; diff --git a/gcc/testsuite/g++.dg/asan/function-argument-1.C b/gcc/testsuite/g++.dg/asan/function-argument-1.C new file mode 100644 index 00000000000..148c4628316 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/function-argument-1.C @@ -0,0 +1,30 @@ +// { dg-do run } +// { dg-shouldfail "asan" } + +struct A +{ + int a[5]; +}; + +static __attribute__ ((noinline)) int +goo (A *a) +{ + int *ptr = &a->a[0]; + return *(volatile int *) (ptr - 1); +} + +__attribute__ ((noinline)) int +foo (A arg) +{ + return goo (&arg); +} + +int +main () +{ + return foo (A ()); +} + +// { dg-output "ERROR: AddressSanitizer: stack-buffer-underflow on address.*(\n|\r\n|\r)" } +// { dg-output "READ of size . at.*" } +// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* underflows this variable.*" } diff --git a/gcc/testsuite/g++.dg/asan/function-argument-2.C b/gcc/testsuite/g++.dg/asan/function-argument-2.C new file mode 100644 index 00000000000..3a7c33bdaaa --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/function-argument-2.C @@ -0,0 +1,24 @@ +// { dg-do run } +// { dg-shouldfail "asan" } + +static __attribute__ ((noinline)) int +goo (int *a) +{ + return *(volatile int *)a; +} + +__attribute__ ((noinline)) int +foo (char arg) +{ + return goo ((int *)&arg); +} + +int +main () +{ + return foo (12); +} + +// { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow on address.*(\n|\r\n|\r)" } +// { dg-output "READ of size . at.*" } +// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* partially overflows this variable.*" } diff --git a/gcc/testsuite/g++.dg/asan/function-argument-3.C b/gcc/testsuite/g++.dg/asan/function-argument-3.C new file mode 100644 index 00000000000..14617ba8425 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/function-argument-3.C @@ -0,0 +1,27 @@ +// { dg-do run } +// { dg-shouldfail "asan" } + +typedef int v4si __attribute__ ((vector_size (16))); + +static __attribute__ ((noinline)) int +goo (v4si *a) +{ + return (*(volatile v4si *) (a + 1))[2]; +} + +__attribute__ ((noinline)) int +foo (v4si arg) +{ + return goo (&arg); +} + +int +main () +{ + v4si v = {1,2,3,4}; + return foo (v); +} + +// { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow on address.*(\n|\r\n|\r)" } +// { dg-output "READ of size . at.*" } +// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* overflows this variable.*" } -- 2.13.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] ASAN: handle addressable params (PR sanitize/81040). 2017-06-20 13:07 ` Martin Liška @ 2017-06-28 13:16 ` Martin Liška 2017-06-29 11:17 ` Jakub Jelinek 1 sibling, 0 replies; 13+ messages in thread From: Martin Liška @ 2017-06-28 13:16 UTC (permalink / raw) To: Jakub Jelinek; +Cc: GCC Patches PING^1 On 06/20/2017 03:06 PM, Martin LiÅ¡ka wrote: > On 06/20/2017 11:32 AM, Jakub Jelinek wrote: >> On Tue, Jun 20, 2017 at 11:23:36AM +0200, Martin LiÅ¡ka wrote: >>>> Then something needs to be done for debugging too. If it is without VTA, >>>> then probably just having DECL_VALUE_EXPR is good enough, otherwise >>>> (VTA) you probably don't want that (or can reset it at that point), but >>>> instead emit after the initialization stmt a debug stmt that the variable >>>> value now lives in a different var. Though ideally we want the debugger >>>> to be able to also change the value of the var, that might be harder. >>>> With DECL_VALUE_EXPR on the other side the debug info will be incorrect in >>>> the prologue until it is assigned to the slot. >>> >>> Here I'm not sure about how to distinguish whether to build or not to build >>> the debug statement. According to flag_var_tracking? >> >> More like if (target_for_debug_bind (arg)) >> And if that is false, just make sure DECL_VALUE_EXPR is set to var. >> >>> You mean something like: >>> g = gimple_build_debug_bind (arg, var, g); >>> ? >> >> Well, there is no stmt, so the last argument would be just NULL. >> >>>> I don't understand the distinction. If you turn the original parm >>>> for complex/vector DECL_GIMPLE_REG_P, you should need the exact same code >>>> (but I think it would be better to use the default SSA_NAME of the PARM_DECL >>>> if it is a gimple reg type, rather than use the PARM_DECL itself >>>> and wait for update_ssa). >>> >>> Yes, the test-case /gcc/testsuite/g++.dg/asan/function-argument-3.C fails for me >>> as one needs to have a temporary SSA name, otherwise: >>> >>> /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/asan/function-argument-3.C:13:1: error: invalid rhs for gimple memory store >>> foo (v4si arg) >>> ^~~ >>> arg >>> >>> arg >>> >>> # .MEM_4 = VDEF <.MEM_1(D)> >>> arg = arg; >>> during GIMPLE pass: sanopt >>> >>> If I see correctly the function in my test-case does not have default def SSA name for the parameter. >>> Thus I guess I need to create a SSA name? >> >> I'd expect if you have DECL_GIMPLE_REG_P set on the PARM_DECL and >> use the default def, you shouldn't run into this. >> >> Jakub >> > > Good I fixed that in v2, that passes regression tests. > Ale objections should be resolved in the version. > > Ready for trunk? > Martin > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] ASAN: handle addressable params (PR sanitize/81040). 2017-06-20 13:07 ` Martin Liška 2017-06-28 13:16 ` Martin Liška @ 2017-06-29 11:17 ` Jakub Jelinek 2017-06-30 9:21 ` Martin Liška 1 sibling, 1 reply; 13+ messages in thread From: Jakub Jelinek @ 2017-06-29 11:17 UTC (permalink / raw) To: Martin Liška; +Cc: GCC Patches On Tue, Jun 20, 2017 at 03:06:56PM +0200, Martin LiÅ¡ka wrote: > +/* Rewrite all usages of tree OP which is a PARM_DECL with a VAR_DECL > + that is it's DECL_VALUE_EXPR. */ > + > +static tree > +rewrite_usage_of_param (tree *op, int *walk_subtrees, void *) > +{ > + if (TREE_CODE (*op) == PARM_DECL && DECL_VALUE_EXPR (*op) != NULL_TREE) DECL_VALUE_EXPR testing is costly (it is a hash table lookup). Therefore you should test DECL_HAS_VALUE_EXPR_P (*op) after checking == PARM_DECL. And DECL_HAS_VALUE_EXPR_P should apply non-NULL DECL_VALUE_EXPR. That said, I wonder if we don't create DECL_VALUE_EXPR for PARM_DECLs in other parts of the compiler, whether it wouldn't be safer to also test here after == PARM_DECL and DECL_HAS_VALUE_EXPR_P check whether *op is in addressable_params hash table. > + { > + *op = DECL_VALUE_EXPR (*op); > + *walk_subtrees = 0; > + } > + > + return NULL; > +} > + > +/* For a given function FUN, rewrite all addressable parameters so that > + a new automatic variable is introduced. Right after function entry > + a parameter is assigned to the variable. */ > + > +static void > +sanitize_rewrite_addressable_params (function *fun) > +{ > + gimple *g; > + gimple_seq stmts = NULL; > + auto_vec<tree> addressable_params; You don't really use the addressable_params vector anywhere, right? Except for: > + > + for (tree arg = DECL_ARGUMENTS (current_function_decl); > + arg; arg = DECL_CHAIN (arg)) > + { > + if (TREE_ADDRESSABLE (arg) && !TREE_ADDRESSABLE (TREE_TYPE (arg))) > + { > + TREE_ADDRESSABLE (arg) = 0; > + /* The parameter is no longer addressable. */ > + tree type = TREE_TYPE (arg); > + addressable_params.safe_push (arg); pushing stuff into it and later > + if (addressable_params.is_empty ()) > + return; If you only need that, a bool flag if any params have been changed is enough. But see above whether it wouldn't be safer to use a hash table to verify it. Plus, I think it would be desirable to clear DECL_HAS_VALUE_EXPR_P and SET_DECL_VALUE_EXPR to NULL afterwards if (target_for_debug_bind (arg)) - whch can be done either the with vec or with a hash table traversal, for that we don't care about the ordering. > + > + /* Create a new automatic variable. */ > + tree var = build_decl (DECL_SOURCE_LOCATION (arg), > + VAR_DECL, DECL_NAME (arg), type); > + TREE_ADDRESSABLE (var) = 1; > + DECL_ARTIFICIAL (var) = 1; > + DECL_SEEN_IN_BIND_EXPR_P (var) = 0; This is 0 already from build_decl, IMHO no need to set it. > + gimple_add_tmp_var (var); > + > + if (dump_file) > + fprintf (dump_file, > + "Rewriting parameter whose address is taken: %s\n", > + IDENTIFIER_POINTER (DECL_NAME (arg))); > + > + SET_DECL_VALUE_EXPR (arg, var); But obviously you miss setting DECL_HAS_VALUE_EXPR_P here. > + /* Assign value of parameter to newly created variable. */ > + if ((TREE_CODE (type) == COMPLEX_TYPE > + || TREE_CODE (type) == VECTOR_TYPE)) > + { > + /* We need to create a SSA name that will be used for the > + assignment. */ Why don't you just set DECL_GIMPLE_REG_P (arg) = 1; for COMPLEX_TYPE/VECTOR_TYPE? The arg is going to be only used to copy it into the new var. And then just use get_or_create_ssa_default_def, regardless of whether if is complex/vector or other. > + /* Replace all usages of PARM_DECLs with the newly > + created variable VAR. */ > + basic_block bb; > + FOR_EACH_BB_FN (bb, fun) > + { > + gimple_stmt_iterator gsi; > + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) > + { > + gimple *stmt = gsi_stmt (gsi); > + gimple_stmt_iterator it = gsi_for_stmt (stmt); > + walk_gimple_stmt (&it, NULL, rewrite_usage_of_param, NULL); > + } > + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) > + { > + gphi *phi = dyn_cast<gphi *> (gsi_stmt (gsi)); > + for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) > + { > + hash_set<tree> visited_nodes; > + walk_tree (gimple_phi_arg_def_ptr (phi, i), > + rewrite_usage_of_param, NULL, &visited_nodes); > + } Doesn't walk_gimple_stmt on the PHI handle this? Jakub ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] ASAN: handle addressable params (PR sanitize/81040). 2017-06-29 11:17 ` Jakub Jelinek @ 2017-06-30 9:21 ` Martin Liška 2017-06-30 9:31 ` Jakub Jelinek 2017-07-04 8:49 ` [PATCH] ASAN: handle addressable params (PR sanitize/81040) Jakub Jelinek 0 siblings, 2 replies; 13+ messages in thread From: Martin Liška @ 2017-06-30 9:21 UTC (permalink / raw) To: Jakub Jelinek; +Cc: GCC Patches [-- Attachment #1: Type: text/plain, Size: 6088 bytes --] On 06/29/2017 01:17 PM, Jakub Jelinek wrote: > On Tue, Jun 20, 2017 at 03:06:56PM +0200, Martin LiÅ¡ka wrote: >> +/* Rewrite all usages of tree OP which is a PARM_DECL with a VAR_DECL >> + that is it's DECL_VALUE_EXPR. */ >> + >> +static tree >> +rewrite_usage_of_param (tree *op, int *walk_subtrees, void *) >> +{ >> + if (TREE_CODE (*op) == PARM_DECL && DECL_VALUE_EXPR (*op) != NULL_TREE) > > DECL_VALUE_EXPR testing is costly (it is a hash table lookup). > Therefore you should test DECL_HAS_VALUE_EXPR_P (*op) after checking > == PARM_DECL. And DECL_HAS_VALUE_EXPR_P should apply non-NULL > DECL_VALUE_EXPR. > That said, I wonder if we don't create DECL_VALUE_EXPR for PARM_DECLs in > other parts of the compiler, whether it wouldn't be safer to also test here > after == PARM_DECL and DECL_HAS_VALUE_EXPR_P check whether *op is in > addressable_params hash table. Thanks for explanation, DECL_HAS_VALUE_EXPR_P is a flag, while DECL_VALUE_EXPR is a hash table lookup. > >> + { >> + *op = DECL_VALUE_EXPR (*op); >> + *walk_subtrees = 0; >> + } >> + >> + return NULL; >> +} >> + >> +/* For a given function FUN, rewrite all addressable parameters so that >> + a new automatic variable is introduced. Right after function entry >> + a parameter is assigned to the variable. */ >> + >> +static void >> +sanitize_rewrite_addressable_params (function *fun) >> +{ >> + gimple *g; >> + gimple_seq stmts = NULL; >> + auto_vec<tree> addressable_params; > > You don't really use the addressable_params vector anywhere, right? > Except for: > >> + >> + for (tree arg = DECL_ARGUMENTS (current_function_decl); >> + arg; arg = DECL_CHAIN (arg)) >> + { >> + if (TREE_ADDRESSABLE (arg) && !TREE_ADDRESSABLE (TREE_TYPE (arg))) >> + { >> + TREE_ADDRESSABLE (arg) = 0; >> + /* The parameter is no longer addressable. */ >> + tree type = TREE_TYPE (arg); >> + addressable_params.safe_push (arg); > > pushing stuff into it and later > >> + if (addressable_params.is_empty ()) >> + return; > > If you only need that, a bool flag if any params have been changed is > enough. But see above whether it wouldn't be safer to use a hash table > to verify it. Plus, I think it would be desirable to clear > DECL_HAS_VALUE_EXPR_P and SET_DECL_VALUE_EXPR to NULL afterwards > if (target_for_debug_bind (arg)) - whch can be done either the with vec > or with a hash table traversal, for that we don't care about the ordering. Good point, I decided to come up with a flag + vector of arguments where VALUE_EXPR should be set to NULL. > >> + >> + /* Create a new automatic variable. */ >> + tree var = build_decl (DECL_SOURCE_LOCATION (arg), >> + VAR_DECL, DECL_NAME (arg), type); >> + TREE_ADDRESSABLE (var) = 1; >> + DECL_ARTIFICIAL (var) = 1; >> + DECL_SEEN_IN_BIND_EXPR_P (var) = 0; > > This is 0 already from build_decl, IMHO no need to set it. Done. > >> + gimple_add_tmp_var (var); >> + >> + if (dump_file) >> + fprintf (dump_file, >> + "Rewriting parameter whose address is taken: %s\n", >> + IDENTIFIER_POINTER (DECL_NAME (arg))); >> + >> + SET_DECL_VALUE_EXPR (arg, var); > > But obviously you miss setting DECL_HAS_VALUE_EXPR_P here. Likewise. > >> + /* Assign value of parameter to newly created variable. */ >> + if ((TREE_CODE (type) == COMPLEX_TYPE >> + || TREE_CODE (type) == VECTOR_TYPE)) >> + { >> + /* We need to create a SSA name that will be used for the >> + assignment. */ > > Why don't you just set DECL_GIMPLE_REG_P (arg) = 1; for > COMPLEX_TYPE/VECTOR_TYPE? The arg is going to be only used to copy it into > the new var. And then just use get_or_create_ssa_default_def, > regardless of whether if is complex/vector or other. Doing so fails here: $ ./xgcc -B. /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/asan/function-argument-1.C -fsanitize=address during RTL pass: expand /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/asan/function-argument-1.C: In function âint foo(A)â: /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/asan/function-argument-1.C:17:1: internal compiler error: in set_parm_rtl, at cfgexpand.c:1271 foo (A arg) ^~~ 0x938536 set_parm_rtl(tree_node*, rtx_def*) ../../gcc/cfgexpand.c:1271 0xab9813 assign_parms ../../gcc/function.c:3782 0xabc605 expand_function_start(tree_node*) ../../gcc/function.c:5221 0x943e01 execute ../../gcc/cfgexpand.c:6248 > >> + /* Replace all usages of PARM_DECLs with the newly >> + created variable VAR. */ >> + basic_block bb; >> + FOR_EACH_BB_FN (bb, fun) >> + { >> + gimple_stmt_iterator gsi; >> + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) >> + { >> + gimple *stmt = gsi_stmt (gsi); >> + gimple_stmt_iterator it = gsi_for_stmt (stmt); >> + walk_gimple_stmt (&it, NULL, rewrite_usage_of_param, NULL); >> + } >> + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) >> + { >> + gphi *phi = dyn_cast<gphi *> (gsi_stmt (gsi)); >> + for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) >> + { >> + hash_set<tree> visited_nodes; >> + walk_tree (gimple_phi_arg_def_ptr (phi, i), >> + rewrite_usage_of_param, NULL, &visited_nodes); >> + } > > Doesn't walk_gimple_stmt on the PHI handle this? No, I see following in asan bootstrap: ^[2^[1^[2^[2../../gcc/c/c-decl.c: In function âtree_node* grokfield(location_t, c_declarator*, c_declspecs*, tree, tree_node**)â: ../../gcc/c/c-decl.c:7525:1: error: address taken, but ADDRESSABLE bit not set grokfield (location_t loc, ^~~~~~~~~ PHI argument &width; for PHI node iftmp.2774_27 = PHI <&width(16), 0B(61), &width(54)> during GIMPLE pass: sanopt ../../gcc/c/c-decl.c:7525:1: internal compiler error: verify_ssa failed 0x115356db verify_ssa(bool, bool) ../../gcc/tree-ssa.c:1186 0x10f850ff execute_function_todo ../../gcc/passes.c:1996 0x10f8376b do_per_function ../../gcc/passes.c:1655 0x10f853a7 execute_todo ../../gcc/passes.c:2043 Sending new version that I'm going to test. Martin > > Jakub > [-- Attachment #2: 0001-ASAN-handle-addressable-params-PR-sanitize-81040.patch --] [-- Type: text/x-patch, Size: 8388 bytes --] From bd7580c259c0552490d63527782d00926c9c5473 Mon Sep 17 00:00:00 2001 From: marxin <mliska@suse.cz> Date: Wed, 14 Jun 2017 11:40:01 +0200 Subject: [PATCH] ASAN: handle addressable params (PR sanitize/81040). gcc/testsuite/ChangeLog: 2017-06-19 Martin Liska <mliska@suse.cz> PR sanitize/81040 * g++.dg/asan/function-argument-1.C: New test. * g++.dg/asan/function-argument-2.C: New test. * g++.dg/asan/function-argument-3.C: New test. gcc/ChangeLog: 2017-06-19 Martin Liska <mliska@suse.cz> PR sanitize/81040 * sanopt.c (rewrite_usage_of_param): New function. (sanitize_rewrite_addressable_params): Likewise. (pass_sanopt::execute): Call rewrite_usage_of_param. --- gcc/sanopt.c | 135 ++++++++++++++++++++++++ gcc/testsuite/g++.dg/asan/function-argument-1.C | 30 ++++++ gcc/testsuite/g++.dg/asan/function-argument-2.C | 24 +++++ gcc/testsuite/g++.dg/asan/function-argument-3.C | 27 +++++ 4 files changed, 216 insertions(+) create mode 100644 gcc/testsuite/g++.dg/asan/function-argument-1.C create mode 100644 gcc/testsuite/g++.dg/asan/function-argument-2.C create mode 100644 gcc/testsuite/g++.dg/asan/function-argument-3.C diff --git a/gcc/sanopt.c b/gcc/sanopt.c index 16bdba76042..acb09dddd5b 100644 --- a/gcc/sanopt.c +++ b/gcc/sanopt.c @@ -37,6 +37,12 @@ along with GCC; see the file COPYING3. If not see #include "gimple-ssa.h" #include "tree-phinodes.h" #include "ssa-iterators.h" +#include "gimplify.h" +#include "gimple-iterator.h" +#include "gimple-walk.h" +#include "cfghooks.h" +#include "tree-dfa.h" +#include "tree-ssa.h" /* This is used to carry information about basic blocks. It is attached to the AUX field of the standard CFG block. */ @@ -858,6 +864,132 @@ sanitize_asan_mark_poison (void) } } +/* Rewrite all usages of tree OP which is a PARM_DECL with a VAR_DECL + that is it's DECL_VALUE_EXPR. */ + +static tree +rewrite_usage_of_param (tree *op, int *walk_subtrees, void *) +{ + if (TREE_CODE (*op) == PARM_DECL && DECL_HAS_VALUE_EXPR_P (*op)) + { + *op = DECL_VALUE_EXPR (*op); + *walk_subtrees = 0; + } + + return NULL; +} + +/* For a given function FUN, rewrite all addressable parameters so that + a new automatic variable is introduced. Right after function entry + a parameter is assigned to the variable. */ + +static void +sanitize_rewrite_addressable_params (function *fun) +{ + gimple *g; + gimple_seq stmts = NULL; + bool has_any_addressable_param = false; + auto_vec<tree> clear_value_expr_list; + + for (tree arg = DECL_ARGUMENTS (current_function_decl); + arg; arg = DECL_CHAIN (arg)) + { + if (TREE_ADDRESSABLE (arg) && !TREE_ADDRESSABLE (TREE_TYPE (arg))) + { + TREE_ADDRESSABLE (arg) = 0; + /* The parameter is no longer addressable. */ + tree type = TREE_TYPE (arg); + has_any_addressable_param = true; + + /* Create a new automatic variable. */ + tree var = build_decl (DECL_SOURCE_LOCATION (arg), + VAR_DECL, DECL_NAME (arg), type); + TREE_ADDRESSABLE (var) = 1; + DECL_ARTIFICIAL (var) = 1; + + gimple_add_tmp_var (var); + + if (dump_file) + fprintf (dump_file, + "Rewriting parameter whose address is taken: %s\n", + IDENTIFIER_POINTER (DECL_NAME (arg))); + + DECL_HAS_VALUE_EXPR_P (arg) = 1; + SET_DECL_VALUE_EXPR (arg, var); + + /* Assign value of parameter to newly created variable. */ + if ((TREE_CODE (type) == COMPLEX_TYPE + || TREE_CODE (type) == VECTOR_TYPE)) + { + /* We need to create a SSA name that will be used for the + assignment. */ + DECL_GIMPLE_REG_P (arg) = 1; + tree tmp = get_or_create_ssa_default_def (cfun, arg); + g = gimple_build_assign (var, tmp); + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); + gimple_seq_add_stmt (&stmts, g); + } + else + { + g = gimple_build_assign (var, arg); + gimple_set_location (g, DECL_SOURCE_LOCATION (arg)); + gimple_seq_add_stmt (&stmts, g); + } + + if (target_for_debug_bind (arg)) + { + g = gimple_build_debug_bind (arg, var, NULL); + gimple_seq_add_stmt (&stmts, g); + clear_value_expr_list.safe_push (arg); + } + } + } + + if (!has_any_addressable_param) + return; + + /* Replace all usages of PARM_DECLs with the newly + created variable VAR. */ + basic_block bb; + FOR_EACH_BB_FN (bb, fun) + { + gimple_stmt_iterator gsi; + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + gimple_stmt_iterator it = gsi_for_stmt (stmt); + walk_gimple_stmt (&it, NULL, rewrite_usage_of_param, NULL); + } + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gphi *phi = dyn_cast<gphi *> (gsi_stmt (gsi)); + for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) + { + hash_set<tree> visited_nodes; + walk_tree (gimple_phi_arg_def_ptr (phi, i), + rewrite_usage_of_param, NULL, &visited_nodes); + } + } + } + + /* Unset value expr for parameters for which we created debug bind + expressions. */ + unsigned i; + tree arg; + FOR_EACH_VEC_ELT (clear_value_expr_list, i, arg) + { + DECL_HAS_VALUE_EXPR_P (arg) = 0; + SET_DECL_VALUE_EXPR (arg, NULL_TREE); + } + + /* Insert default assignments at the beginning of a function. */ + basic_block entry_bb = ENTRY_BLOCK_PTR_FOR_FN (fun); + entry_bb = split_edge (single_succ_edge (entry_bb)); + + gimple_stmt_iterator gsi = gsi_start_bb (entry_bb); + gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT); +} + unsigned int pass_sanopt::execute (function *fun) { @@ -891,6 +1023,9 @@ pass_sanopt::execute (function *fun) sanitize_asan_mark_poison (); } + if (asan_sanitize_stack_p ()) + sanitize_rewrite_addressable_params (fun); + bool use_calls = ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD < INT_MAX && asan_num_accesses >= ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD; diff --git a/gcc/testsuite/g++.dg/asan/function-argument-1.C b/gcc/testsuite/g++.dg/asan/function-argument-1.C new file mode 100644 index 00000000000..148c4628316 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/function-argument-1.C @@ -0,0 +1,30 @@ +// { dg-do run } +// { dg-shouldfail "asan" } + +struct A +{ + int a[5]; +}; + +static __attribute__ ((noinline)) int +goo (A *a) +{ + int *ptr = &a->a[0]; + return *(volatile int *) (ptr - 1); +} + +__attribute__ ((noinline)) int +foo (A arg) +{ + return goo (&arg); +} + +int +main () +{ + return foo (A ()); +} + +// { dg-output "ERROR: AddressSanitizer: stack-buffer-underflow on address.*(\n|\r\n|\r)" } +// { dg-output "READ of size . at.*" } +// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* underflows this variable.*" } diff --git a/gcc/testsuite/g++.dg/asan/function-argument-2.C b/gcc/testsuite/g++.dg/asan/function-argument-2.C new file mode 100644 index 00000000000..3a7c33bdaaa --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/function-argument-2.C @@ -0,0 +1,24 @@ +// { dg-do run } +// { dg-shouldfail "asan" } + +static __attribute__ ((noinline)) int +goo (int *a) +{ + return *(volatile int *)a; +} + +__attribute__ ((noinline)) int +foo (char arg) +{ + return goo ((int *)&arg); +} + +int +main () +{ + return foo (12); +} + +// { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow on address.*(\n|\r\n|\r)" } +// { dg-output "READ of size . at.*" } +// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* partially overflows this variable.*" } diff --git a/gcc/testsuite/g++.dg/asan/function-argument-3.C b/gcc/testsuite/g++.dg/asan/function-argument-3.C new file mode 100644 index 00000000000..14617ba8425 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/function-argument-3.C @@ -0,0 +1,27 @@ +// { dg-do run } +// { dg-shouldfail "asan" } + +typedef int v4si __attribute__ ((vector_size (16))); + +static __attribute__ ((noinline)) int +goo (v4si *a) +{ + return (*(volatile v4si *) (a + 1))[2]; +} + +__attribute__ ((noinline)) int +foo (v4si arg) +{ + return goo (&arg); +} + +int +main () +{ + v4si v = {1,2,3,4}; + return foo (v); +} + +// { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow on address.*(\n|\r\n|\r)" } +// { dg-output "READ of size . at.*" } +// { dg-output ".*'arg' <== Memory access at offset \[0-9\]* overflows this variable.*" } -- 2.13.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] ASAN: handle addressable params (PR sanitize/81040). 2017-06-30 9:21 ` Martin Liška @ 2017-06-30 9:31 ` Jakub Jelinek 2017-07-04 7:47 ` [PATCH] Enable addressable params sanitization with --param asan-stack=1 Martin Liška 2017-07-04 8:49 ` [PATCH] ASAN: handle addressable params (PR sanitize/81040) Jakub Jelinek 1 sibling, 1 reply; 13+ messages in thread From: Jakub Jelinek @ 2017-06-30 9:31 UTC (permalink / raw) To: Martin Liška; +Cc: GCC Patches On Fri, Jun 30, 2017 at 11:21:48AM +0200, Martin LiÅ¡ka wrote: > @@ -858,6 +864,132 @@ sanitize_asan_mark_poison (void) > } > } > > +/* Rewrite all usages of tree OP which is a PARM_DECL with a VAR_DECL > + that is it's DECL_VALUE_EXPR. */ > + > +static tree > +rewrite_usage_of_param (tree *op, int *walk_subtrees, void *) > +{ > + if (TREE_CODE (*op) == PARM_DECL && DECL_HAS_VALUE_EXPR_P (*op)) > + { > + *op = DECL_VALUE_EXPR (*op); > + *walk_subtrees = 0; > + } If you are going to rely just on DECL_HAS_VALUE_EXPR_P here > + for (tree arg = DECL_ARGUMENTS (current_function_decl); > + arg; arg = DECL_CHAIN (arg)) > + { I think you should gcc_assert here that !DECL_HAS_VALUE_EXPR_P (arg) here. If that ever fails, another possibility would be to temporarily clear those flags and remember it and then set it again after the walk_*. The question would be what to do with arguments that already have DECL_VALUE_EXPR, are addressable and you want to rewrite them. > + if (TREE_ADDRESSABLE (arg) && !TREE_ADDRESSABLE (TREE_TYPE (arg))) > + { > + TREE_ADDRESSABLE (arg) = 0; > + /* The parameter is no longer addressable. */ > + tree type = TREE_TYPE (arg); > + has_any_addressable_param = true; Otherwise LGTM. Jakub ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH] Enable addressable params sanitization with --param asan-stack=1. 2017-06-30 9:31 ` Jakub Jelinek @ 2017-07-04 7:47 ` Martin Liška 2017-07-04 8:00 ` Jakub Jelinek 0 siblings, 1 reply; 13+ messages in thread From: Martin Liška @ 2017-07-04 7:47 UTC (permalink / raw) To: Jakub Jelinek; +Cc: GCC Patches [-- Attachment #1: Type: text/plain, Size: 565 bytes --] Hello. As mentioned in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81040#c15, the sanitization is done only when one uses use-after-scope. That's caused by fact that I decorated the newly created auto variables with DECL_ARTIFICIAL = 1. Because of that static inline bool asan_protect_stack_decl (tree decl) { return DECL_P (decl) && (!DECL_ARTIFICIAL (decl) || (asan_sanitize_use_after_scope () && TREE_ADDRESSABLE (decl))); } returns false. I hope not marking the variable as DECL_ARTIFICIAL will work fine? Or am I missing something? Thanks, Martin [-- Attachment #2: 0001-Enable-addressable-params-sanitization-with-param-as.patch --] [-- Type: text/x-patch, Size: 1575 bytes --] From b79133e3c9ad41b44f0a12c574fc1d0b8348ad89 Mon Sep 17 00:00:00 2001 From: marxin <mliska@suse.cz> Date: Tue, 4 Jul 2017 09:22:23 +0200 Subject: [PATCH] Enable addressable params sanitization with --param asan-stack=1. gcc/ChangeLog: 2017-07-04 Martin Liska <mliska@suse.cz> PR sanitizer/81040 * sanopt.c (sanitize_rewrite_addressable_params): Do not decorate variable as DECL_ARTIFICIAL in order to sanitize it. gcc/testsuite/ChangeLog: 2017-07-04 Martin Liska <mliska@suse.cz> PR sanitizer/81040 * g++.dg/asan/function-argument-1.C: Run the test-case w/o use-after-scope sanitization. --- gcc/sanopt.c | 1 - gcc/testsuite/g++.dg/asan/function-argument-1.C | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/sanopt.c b/gcc/sanopt.c index 7692f6a9db7..8c80ff37d4d 100644 --- a/gcc/sanopt.c +++ b/gcc/sanopt.c @@ -905,7 +905,6 @@ sanitize_rewrite_addressable_params (function *fun) tree var = build_decl (DECL_SOURCE_LOCATION (arg), VAR_DECL, DECL_NAME (arg), type); TREE_ADDRESSABLE (var) = 1; - DECL_ARTIFICIAL (var) = 1; gimple_add_tmp_var (var); diff --git a/gcc/testsuite/g++.dg/asan/function-argument-1.C b/gcc/testsuite/g++.dg/asan/function-argument-1.C index 148c4628316..bdbb37a44a4 100644 --- a/gcc/testsuite/g++.dg/asan/function-argument-1.C +++ b/gcc/testsuite/g++.dg/asan/function-argument-1.C @@ -1,5 +1,6 @@ // { dg-do run } // { dg-shouldfail "asan" } +// { dg-options "-fsanitize=address -fno-sanitize-address-use-after-scope" } struct A { -- 2.13.2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Enable addressable params sanitization with --param asan-stack=1. 2017-07-04 7:47 ` [PATCH] Enable addressable params sanitization with --param asan-stack=1 Martin Liška @ 2017-07-04 8:00 ` Jakub Jelinek 2017-07-04 10:52 ` Martin Liška 0 siblings, 1 reply; 13+ messages in thread From: Jakub Jelinek @ 2017-07-04 8:00 UTC (permalink / raw) To: Martin Liška; +Cc: GCC Patches On Tue, Jul 04, 2017 at 09:47:29AM +0200, Martin LiÅ¡ka wrote: > As mentioned in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81040#c15, the sanitization is > done only when one uses use-after-scope. That's caused by fact that I decorated the newly > created auto variables with DECL_ARTIFICIAL = 1. Because of that > > static inline bool > asan_protect_stack_decl (tree decl) > { > return DECL_P (decl) > && (!DECL_ARTIFICIAL (decl) > || (asan_sanitize_use_after_scope () && TREE_ADDRESSABLE (decl))); > } > > returns false. I hope not marking the variable as DECL_ARTIFICIAL will work fine? > Or am I missing something? Well, you should make sure the debug info is correct. Which means ideally that there is just one DW_TAG_formal_parameter and no DW_TAG_variable for the parameter. For the addressable parameters I hope the corresponding artificial vars just live in memory for the whole rest of the scope, at least for the case where you emit a debug bind (hope it is after the assignment to the artificial var) I think it should be fine to set DECL_IGNORED_P on the artificial var instead of DECL_ARTIFICIAL. For the other case where there is DECL_VALUE_EXPR, perhaps try it too and see what you get. Jakub ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Enable addressable params sanitization with --param asan-stack=1. 2017-07-04 8:00 ` Jakub Jelinek @ 2017-07-04 10:52 ` Martin Liška 0 siblings, 0 replies; 13+ messages in thread From: Martin Liška @ 2017-07-04 10:52 UTC (permalink / raw) To: Jakub Jelinek; +Cc: GCC Patches [-- Attachment #1: Type: text/plain, Size: 1465 bytes --] On 07/04/2017 09:59 AM, Jakub Jelinek wrote: > On Tue, Jul 04, 2017 at 09:47:29AM +0200, Martin LiÅ¡ka wrote: >> As mentioned in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81040#c15, the sanitization is >> done only when one uses use-after-scope. That's caused by fact that I decorated the newly >> created auto variables with DECL_ARTIFICIAL = 1. Because of that >> >> static inline bool >> asan_protect_stack_decl (tree decl) >> { >> return DECL_P (decl) >> && (!DECL_ARTIFICIAL (decl) >> || (asan_sanitize_use_after_scope () && TREE_ADDRESSABLE (decl))); >> } >> >> returns false. I hope not marking the variable as DECL_ARTIFICIAL will work fine? >> Or am I missing something? > > Well, you should make sure the debug info is correct. > Which means ideally that there is just one DW_TAG_formal_parameter and no > DW_TAG_variable for the parameter. > For the addressable parameters I hope the corresponding artificial > vars just live in memory for the whole rest of the scope, at least for the > case where you emit a debug bind (hope it is after the assignment to the > artificial var) I think it should be fine to set DECL_IGNORED_P on the > artificial var instead of DECL_ARTIFICIAL. > For the other case where there is DECL_VALUE_EXPR, perhaps try it too and > see what you get. > > Jakub > Using DECL_IGNORED_P works for me. Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. I'm going to install the patch. Martin [-- Attachment #2: 0001-Enable-addressable-params-sanitization-with-param-as.patch --] [-- Type: text/x-patch, Size: 1589 bytes --] From 20d69fbf4076add09df363ffb9d03cd243f8190d Mon Sep 17 00:00:00 2001 From: marxin <mliska@suse.cz> Date: Tue, 4 Jul 2017 09:22:23 +0200 Subject: [PATCH] Enable addressable params sanitization with --param asan-stack=1. gcc/ChangeLog: 2017-07-04 Martin Liska <mliska@suse.cz> PR sanitizer/81040 * sanopt.c (sanitize_rewrite_addressable_params): Mark the newly created variable as DECL_IGNORED_P. gcc/testsuite/ChangeLog: 2017-07-04 Martin Liska <mliska@suse.cz> PR sanitizer/81040 * g++.dg/asan/function-argument-1.C: Run the test-case w/o use-after-scope sanitization. --- gcc/sanopt.c | 2 +- gcc/testsuite/g++.dg/asan/function-argument-1.C | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/sanopt.c b/gcc/sanopt.c index 7692f6a9db7..b7740741d43 100644 --- a/gcc/sanopt.c +++ b/gcc/sanopt.c @@ -905,7 +905,7 @@ sanitize_rewrite_addressable_params (function *fun) tree var = build_decl (DECL_SOURCE_LOCATION (arg), VAR_DECL, DECL_NAME (arg), type); TREE_ADDRESSABLE (var) = 1; - DECL_ARTIFICIAL (var) = 1; + DECL_IGNORED_P (var) = 1; gimple_add_tmp_var (var); diff --git a/gcc/testsuite/g++.dg/asan/function-argument-1.C b/gcc/testsuite/g++.dg/asan/function-argument-1.C index 148c4628316..bdbb37a44a4 100644 --- a/gcc/testsuite/g++.dg/asan/function-argument-1.C +++ b/gcc/testsuite/g++.dg/asan/function-argument-1.C @@ -1,5 +1,6 @@ // { dg-do run } // { dg-shouldfail "asan" } +// { dg-options "-fsanitize=address -fno-sanitize-address-use-after-scope" } struct A { -- 2.13.2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] ASAN: handle addressable params (PR sanitize/81040). 2017-06-30 9:21 ` Martin Liška 2017-06-30 9:31 ` Jakub Jelinek @ 2017-07-04 8:49 ` Jakub Jelinek 1 sibling, 0 replies; 13+ messages in thread From: Jakub Jelinek @ 2017-07-04 8:49 UTC (permalink / raw) To: Martin Liška; +Cc: GCC Patches On Fri, Jun 30, 2017 at 11:21:48AM +0200, Martin LiÅ¡ka wrote: > --- /dev/null > +++ b/gcc/testsuite/g++.dg/asan/function-argument-3.C > @@ -0,0 +1,27 @@ > +// { dg-do run } > +// { dg-shouldfail "asan" } > + > +typedef int v4si __attribute__ ((vector_size (16))); > + > +static __attribute__ ((noinline)) int > +goo (v4si *a) > +{ > + return (*(volatile v4si *) (a + 1))[2]; > +} > + > +__attribute__ ((noinline)) int > +foo (v4si arg) > +{ > + return goo (&arg); > +} This test fails on i686-linux when -msse2 is not on by default, fixed thusly, committed as obvious: 2017-07-04 Jakub Jelinek <jakub@redhat.com> * g++.dg/asan/function-argument-3.C: Add -Wno-psabi to additional options. --- gcc/testsuite/g++.dg/asan/function-argument-3.C.jj 2017-07-03 19:03:25.000000000 +0200 +++ gcc/testsuite/g++.dg/asan/function-argument-3.C 2017-07-04 10:42:18.558716171 +0200 @@ -1,5 +1,6 @@ // { dg-do run } // { dg-shouldfail "asan" } +// { dg-additional-options "-Wno-psabi" } typedef int v4si __attribute__ ((vector_size (16))); Jakub ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2017-07-04 10:52 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-06-19 13:50 [PATCH] ASAN: handle addressable params (PR sanitize/81040) Martin Liška 2017-06-19 14:13 ` Jakub Jelinek 2017-06-20 9:23 ` Martin Liška 2017-06-20 9:32 ` Jakub Jelinek 2017-06-20 13:07 ` Martin Liška 2017-06-28 13:16 ` Martin Liška 2017-06-29 11:17 ` Jakub Jelinek 2017-06-30 9:21 ` Martin Liška 2017-06-30 9:31 ` Jakub Jelinek 2017-07-04 7:47 ` [PATCH] Enable addressable params sanitization with --param asan-stack=1 Martin Liška 2017-07-04 8:00 ` Jakub Jelinek 2017-07-04 10:52 ` Martin Liška 2017-07-04 8:49 ` [PATCH] ASAN: handle addressable params (PR sanitize/81040) Jakub Jelinek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).