diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 35ca276e4ad..c735e9ca2a3 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1128,9 +1128,18 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) MAX (alignb, ASAN_RED_ZONE_SIZE), !FRAME_GROWS_DOWNWARD); tree repr_decl = NULL_TREE; + poly_uint64 size = stack_vars[i].size; + /* For small variables shrink middle redzone (including + * variable store) just to ASAN_RED_ZONE_SIZE. */ + if (ASAN_STACK_SMALL_REDZONE + && i != n - 1 + && (stack_vars[i].size.to_constant () + <= (ASAN_RED_ZONE_SIZE / 2))) + ; + else + size += ASAN_RED_ZONE_SIZE; offset - = alloc_stack_frame_space (stack_vars[i].size - + ASAN_RED_ZONE_SIZE, + = alloc_stack_frame_space (size, MAX (alignb, ASAN_RED_ZONE_SIZE)); data->asan_vec.safe_push (prev_offset); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7ef4e7a449b..1c55887b9cd 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -11313,6 +11313,9 @@ Enable buffer overflow detection for stack objects. This kind of protection is enabled by default when using @option{-fsanitize=address}. To disable stack protection use @option{--param asan-stack=0} option. +@item asan-stack-small-redzone +Emit smaller middle redzone for variables smaller or equal to 16 bytes. + @item asan-instrument-reads Enable buffer overflow detection for memory reads. This kind of protection is enabled by default when using @option{-fsanitize=address}. diff --git a/gcc/params.def b/gcc/params.def index 9f0697327d4..f1fafb4002d 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -1201,6 +1201,12 @@ DEFPARAM (PARAM_ASAN_STACK, "Enable asan stack protection.", 1, 0, 1) +DEFPARAM (PARAM_ASAN_STACK_SMALL_REDZONE, + "asan-stack-small-redzone", + "Emit smaller middle redzone for variables smaller " + "or equal to 16 bytes.", + 0, 0, 1) + DEFPARAM (PARAM_ASAN_PROTECT_ALLOCAS, "asan-instrument-allocas", "Enable asan allocas/VLAs protection.", diff --git a/gcc/params.h b/gcc/params.h index 8aa960a904e..42df40e66fd 100644 --- a/gcc/params.h +++ b/gcc/params.h @@ -236,6 +236,8 @@ extern void init_param_values (int *params); PARAM_VALUE (PARAM_ALLOW_PACKED_STORE_DATA_RACES) #define ASAN_STACK \ PARAM_VALUE (PARAM_ASAN_STACK) +#define ASAN_STACK_SMALL_REDZONE \ + PARAM_VALUE (PARAM_ASAN_STACK_SMALL_REDZONE) #define ASAN_PROTECT_ALLOCAS \ PARAM_VALUE (PARAM_ASAN_PROTECT_ALLOCAS) #define ASAN_GLOBALS \ diff --git a/gcc/testsuite/c-c++-common/asan/asan-stack-small.c b/gcc/testsuite/c-c++-common/asan/asan-stack-small.c new file mode 100644 index 00000000000..dc08edaad71 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/asan-stack-small.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-options "--param asan-stack-small-redzone=1" } */ + +char *pa; +char *pb; +char *pc; + +void access (volatile char *ptr) +{ + *ptr = 'x'; +} + +int main (int argc, char **argv) +{ + char a; + char b; + char c; + + pa = &a; + pb = &b; + pc = &c; + + access (pb); + access (pc); + // access 'b' here + access (pa + 32); + + return 0; +}