diff --git a/gcc/asan.c b/gcc/asan.c index e71ab2cc710..235e219479d 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -253,7 +253,7 @@ static tree last_alloca_addr; /* Set of variable declarations that are going to be guarded by use-after-scope sanitizer. */ -static hash_set *asan_handled_variables = NULL; +hash_set *asan_handled_variables = NULL; hash_set *asan_used_labels = NULL; diff --git a/gcc/asan.h b/gcc/asan.h index 412af220597..2f431b4f938 100644 --- a/gcc/asan.h +++ b/gcc/asan.h @@ -110,6 +110,8 @@ extern bool asan_sanitize_stack_p (void); extern bool asan_sanitize_allocas_p (void); +extern hash_set *asan_handled_variables; + /* Return TRUE if builtin with given FCODE will be intercepted by libasan. */ diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index c8d7805308c..35ca276e4ad 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1155,6 +1155,20 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) if (repr_decl == NULL_TREE) repr_decl = stack_vars[i].decl; data->asan_decl_vec.safe_push (repr_decl); + + /* Make sure a representative is unpoison if another + variable in the partition is handled by + use-after-scope sanitization. */ + if (asan_handled_variables != NULL + && !asan_handled_variables->contains (repr_decl)) + { + for (j = i; j != EOC; j = stack_vars[j].next) + if (asan_handled_variables->contains (stack_vars[j].decl)) + break; + if (j != EOC) + asan_handled_variables->add (repr_decl); + } + data->asan_alignb = MAX (data->asan_alignb, alignb); if (data->asan_base == NULL) data->asan_base = gen_reg_rtx (Pmode); diff --git a/gcc/testsuite/g++.dg/asan/pr85774.C b/gcc/testsuite/g++.dg/asan/pr85774.C new file mode 100644 index 00000000000..c033abfd69b --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/pr85774.C @@ -0,0 +1,51 @@ +/* PR sanitizer/85774 */ +/* { dg-do run } */ + +#include + +void +DoSomething () +{ +} + +void +DoFunc (const std::function &func) +{ + func (); +} + +void +Setup () +{ + switch (1) + { + case 1: + { + DoFunc ([]() {}); + break; + } + case 2: + { + DoFunc ([]() {}); + break; + } + default: + break; + } + + DoSomething (); +} + +void +DemostrateBadPoisoning () +{ + DoFunc ([]() {}); +} + +int +main () +{ + Setup (); + DemostrateBadPoisoning (); + return 0; +}