Skip to content

Commit 1493c24

Browse files
authored
[ASan][test] Fix TestCases/Posix/stack-overflow.cpp on Solaris/sparcv9 (#109101)
When ASan testing is enabled on SPARC as per PR #107405, the ``` AddressSanitizer-sparc-sunos :: TestCases/Posix/stack-overflow.cpp ``` test `FAIL`s: ``` compiler-rt/test/asan/TestCases/Posix/stack-overflow.cpp:80:12: error: CHECK: expected string not found in input // CHECK: {{stack-overflow on address 0x.* \(pc 0x.* bp 0x.* sp 0x.* T.*\)}} ^ AddressSanitizer:DEADLYSIGNAL AddressSanitizer:DEADLYSIGNAL ================================================================= ==11358==ERROR: AddressSanitizer: SEGV on unknown address 0xff3fff90 (pc 0x000db0c0 bp 0xfeed59f8 sp 0xfeed5978 T0) ==11358==The signal is caused by a READ memory access. AddressSanitizer:DEADLYSIGNAL AddressSanitizer: nested bug in the same thread, aborting. ``` It turns out that `sanitizer_linux.cpp` (`GetPcSpBp`) tries to dereference the stack pointer to get at the saved frame pointer, which cannot work since `sp` has been invalidated by the stack overflow in the test. The access attempt thus leads to a second `SEGV`. Solaris `walkcontext(3C)` doesn't have that problem: in the original OpenSolaris sources (`$SRC/lib/libc/port/gen/walkstack.c`) they used `/proc/self/as` to avoid the fault, which is quite heavy-handed. Solaris 11.4 uses a non-faulting load instead (`load_no_fault_uint32`, which just uses the `lduwa` insn). This patch follows this lead, returning a `NULL` `bp` in the failure case. Unfortunately, this leads to `SEGV`s in the depth of the unwinder, so this patch avoids printing a stack trace in this case. Tested on `sparcv9-sun-solaris2.11` and `sparc64-unknown-linux-gnu`.
1 parent 5ca09d6 commit 1493c24

File tree

2 files changed

+25
-8
lines changed

2 files changed

+25
-8
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp

+16-2
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ extern struct ps_strings *__ps_strings;
107107
# endif // SANITIZER_NETBSD
108108

109109
# if SANITIZER_SOLARIS
110+
# include <stddef.h>
110111
# include <stdlib.h>
112+
# include <sys/frame.h>
111113
# include <thread.h>
112114
# define environ _environ
113115
# endif
@@ -2617,7 +2619,19 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
26172619
# if SANITIZER_SOLARIS
26182620
ucontext_t *ucontext = (ucontext_t *)context;
26192621
*pc = ucontext->uc_mcontext.gregs[REG_PC];
2620-
*sp = ucontext->uc_mcontext.gregs[REG_O6] + STACK_BIAS;
2622+
*sp = ucontext->uc_mcontext.gregs[REG_SP] + STACK_BIAS;
2623+
// Avoid SEGV when dereferencing sp on stack overflow with non-faulting load.
2624+
// This requires a SPARC V9 CPU. Cannot use #ASI_PNF here: only supported
2625+
// since clang-19.
2626+
# if defined(__sparcv9)
2627+
asm("ldxa [%[fp]] 0x82, %[bp]"
2628+
# else
2629+
asm("lduwa [%[fp]] 0x82, %[bp]"
2630+
# endif
2631+
: [bp] "=r"(*bp)
2632+
: [fp] "r"(&((struct frame *)*sp)->fr_savfp));
2633+
if (*bp)
2634+
*bp += STACK_BIAS;
26212635
# else
26222636
// Historical BSDism here.
26232637
struct sigcontext *scontext = (struct sigcontext *)context;
@@ -2628,8 +2642,8 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
26282642
*pc = scontext->si_regs.pc;
26292643
*sp = scontext->si_regs.u_regs[14];
26302644
# endif
2631-
# endif
26322645
*bp = (uptr)((uhwptr *)*sp)[14] + STACK_BIAS;
2646+
# endif
26332647
# elif defined(__mips__)
26342648
ucontext_t *ucontext = (ucontext_t *)context;
26352649
*pc = ucontext->uc_mcontext.pc;

compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp

+9-6
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,15 @@ static void ReportStackOverflowImpl(const SignalContext &sig, u32 tid,
227227
SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc,
228228
(void *)sig.bp, (void *)sig.sp, tid);
229229
Printf("%s", d.Default());
230-
InternalMmapVector<BufferedStackTrace> stack_buffer(1);
231-
BufferedStackTrace *stack = stack_buffer.data();
232-
stack->Reset();
233-
unwind(sig, unwind_context, stack);
234-
stack->Print();
235-
ReportErrorSummary(kDescription, stack);
230+
// Avoid SEGVs in the unwinder when bp couldn't be determined.
231+
if (sig.bp) {
232+
InternalMmapVector<BufferedStackTrace> stack_buffer(1);
233+
BufferedStackTrace *stack = stack_buffer.data();
234+
stack->Reset();
235+
unwind(sig, unwind_context, stack);
236+
stack->Print();
237+
ReportErrorSummary(kDescription, stack);
238+
}
236239
}
237240

238241
static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,

0 commit comments

Comments
 (0)