diff options
-rw-r--r-- | gcc/asan.cc | 26 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/asan/pr110027.c | 50 |
2 files changed, 73 insertions, 3 deletions
diff --git a/gcc/asan.cc b/gcc/asan.cc index 7f91cc6..57c3a9b 100644 --- a/gcc/asan.cc +++ b/gcc/asan.cc @@ -1911,19 +1911,39 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, } str_cst = asan_pp_string (&asan_pp); + gcc_checking_assert (offsets[0] == (crtl->stack_protect_guard + ? -ASAN_RED_ZONE_SIZE : 0)); /* Emit the prologue sequence. */ if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase && param_asan_use_after_return) { + HOST_WIDE_INT adjusted_frame_size = asan_frame_size; + /* The stack protector guard is allocated at the top of the frame + and cfgexpand.cc then uses align_frame_offset (ASAN_RED_ZONE_SIZE); + while in that case we can still use asan_frame_size, we need to take + that into account when computing base_align_bias. */ + if (alignb > ASAN_RED_ZONE_SIZE && crtl->stack_protect_guard) + adjusted_frame_size += ASAN_RED_ZONE_SIZE; use_after_return_class = floor_log2 (asan_frame_size - 1) - 5; /* __asan_stack_malloc_N guarantees alignment N < 6 ? (64 << N) : 4096 bytes. */ if (alignb > (use_after_return_class < 6 ? (64U << use_after_return_class) : 4096U)) use_after_return_class = -1; - else if (alignb > ASAN_RED_ZONE_SIZE && (asan_frame_size & (alignb - 1))) - base_align_bias = ((asan_frame_size + alignb - 1) - & ~(alignb - HOST_WIDE_INT_1)) - asan_frame_size; + else if (alignb > ASAN_RED_ZONE_SIZE + && (adjusted_frame_size & (alignb - 1))) + { + base_align_bias + = ((adjusted_frame_size + alignb - 1) + & ~(alignb - HOST_WIDE_INT_1)) - adjusted_frame_size; + use_after_return_class + = floor_log2 (asan_frame_size + base_align_bias - 1) - 5; + if (use_after_return_class > 10) + { + base_align_bias = 0; + use_after_return_class = -1; + } + } } /* Align base if target is STRICT_ALIGNMENT. */ diff --git a/gcc/testsuite/gcc.dg/asan/pr110027.c b/gcc/testsuite/gcc.dg/asan/pr110027.c new file mode 100644 index 0000000..6d64689 --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/pr110027.c @@ -0,0 +1,50 @@ +/* PR middle-end/110027 */ +/* { dg-do run } */ +/* { dg-additional-options "-fstack-protector-strong" { target fstack_protector } } */ +/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */ + +struct __attribute__((aligned (128))) S { char s[128]; }; +struct __attribute__((aligned (64))) T { char s[192]; }; +struct __attribute__((aligned (32))) U { char s[256]; }; +struct __attribute__((aligned (64))) V { char s[320]; }; +struct __attribute__((aligned (128))) W { char s[512]; }; + +__attribute__((noipa)) void +foo (void *p, void *q, void *r, void *s) +{ + if (((__UINTPTR_TYPE__) p & 31) != 0 + || ((__UINTPTR_TYPE__) q & 127) != 0 + || ((__UINTPTR_TYPE__) r & 63) != 0) + __builtin_abort (); + (void *) s; +} + +__attribute__((noipa)) int +bar (void) +{ + struct U u; + struct S s; + struct T t; + char p[4]; + foo (&u, &s, &t, &p); + return 42; +} + +__attribute__((noipa)) int +baz (void) +{ + struct W w; + struct U u; + struct V v; + char p[4]; + foo (&u, &w, &v, &p); + return 42; +} + +int +main () +{ + bar (); + baz (); + return 0; +} |