Ada makes extensive use of nested functions, which turn all automatic variables of the enclosing function that are used in nested ones into members of an artificial FRAME record type.
The address of a local variable is usually passed to asan marking functions without using a temporary. Taking the address of a member of FRAME within a nested function, however, is not regarded as a gimple val: while introducing FRAME variables, current_function_decl is always the outermost function, even while processing a nested function, so decl_address_invariant_p returns false for such ADDR_EXPRs. So, as automatic variables are moved into FRAME, any asan call that marks such a variable has its ADDR_EXPR replaced with a SSA_NAME set to the ADDR_EXPR of the FRAME member. asan_expand_mark_ifn was not prepared to deal with ADDR_EXPRs split out into SSA_NAMEs. This patch deals with such cases. [It does NOT deal with PHI nodes and whatnot. I'm not even sure it should. Maybe we want the ADDR_EXPR to be a gimple val instead, but this more conservative fix felt more appropriate for this stage.] Regstrapped on x86_64-linux-gnu. Ok to install? for gcc/ChangeLog * asan.c (asan_expand_mark_ifn): Follow SSA_NAME defs for an ADDR_EXPR base. for gcc/testsuite/ChangeLog * gcc.dg/asan/nested-1.c: New. --- gcc/asan.c | 21 +++++++++++++++++++++ gcc/testsuite/gcc.dg/asan/nested-1.c | 24 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/asan/nested-1.c diff --git a/gcc/asan.c b/gcc/asan.c index 89ecd99b18294..2d2fb97098b2f 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -3629,6 +3629,27 @@ asan_expand_mark_ifn (gimple_stmt_iterator *iter) bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON; tree base = gimple_call_arg (g, 1); + while (TREE_CODE (base) == SSA_NAME) + { + gimple *def = SSA_NAME_DEF_STMT (base); + if (!def) + break; + + if (!is_gimple_assign (def)) + break; + + if (!SINGLE_SSA_TREE_OPERAND (def, SSA_OP_DEF)) + break; + + if (gimple_num_ops (def) != 2) + break; + + if (gimple_expr_code (def) == ADDR_EXPR + || gimple_expr_code (def) == SSA_NAME) + base = gimple_assign_rhs1 (def); + else + break; + } gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR); tree decl = TREE_OPERAND (base, 0); diff --git a/gcc/testsuite/gcc.dg/asan/nested-1.c b/gcc/testsuite/gcc.dg/asan/nested-1.c new file mode 100644 index 0000000000000..87e842098077c --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/nested-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=address" } */ + +int f(int i) { + auto int h() { + int r; + int *p; + + { + int x[3]; + + auto int g() { + return x[i]; + } + + p = &r; + *p = g(); + } + + return *p; + } + + return h(); +} -- Alexandre Oliva, happy hacker https://FSFLA.org/blogs/lxo/ Free Software Activist GNU Toolchain Engineer Vim, Vi, Voltei pro Emacs -- GNUlius Caesar