aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/asan.cc26
-rw-r--r--gcc/testsuite/gcc.dg/asan/pr110027.c50
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;
+}