From c3525ce6ac9898821dc7cd12554f9ac7eb5fad20 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 4 Apr 2013 06:52:40 +0000 Subject: [PATCH] [sanitizer] while doing fast unwinding make sure that the frame pointer is aligned; fix lint llvm-svn: 178747 --- compiler-rt/lib/msan/msan_interceptors.cc | 2 +- .../sanitizer_common/sanitizer_stacktrace.cc | 1 + .../tests/sanitizer_stacktrace_test.cc | 26 ++++++++++++++++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc index 72cf2f6f2e7d..17b4bf8c1035 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cc +++ b/compiler-rt/lib/msan/msan_interceptors.cc @@ -826,7 +826,7 @@ INTERCEPTOR(int, getrusage, int who, void *usage) { INTERCEPTOR(int, sigaction, int signum, const void *act, void *oldact) { ENSURE_MSAN_INITED(); - // TODO: check that *act is unpoisoned. + // FIXME: check that *act is unpoisoned. // That requires intercepting all of sigemptyset, sigfillset, etc. int res = REAL(sigaction)(signum, act, oldact); if (res == 0) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc index 3533b9c01f77..143019b9efeb 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -137,6 +137,7 @@ void StackTrace::FastUnwindStack(uptr pc, uptr bp, while (frame > prev_frame && frame < (uhwptr *)stack_top - 2 && frame > (uhwptr *)stack_bottom && + IsAligned((uptr)frame, sizeof(*frame)) && size < max_size) { uhwptr pc1 = frame[1]; if (pc1 != pc) { diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc index 202525596871..3d352cb97a5e 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc @@ -28,12 +28,16 @@ class FastUnwindTest : public ::testing::Test { StackTrace trace; }; +static uptr PC(uptr idx) { + return (1<<20) + idx; +} + void FastUnwindTest::SetUp() { // Fill an array of pointers with fake fp+retaddr pairs. Frame pointers have // even indices. for (uptr i = 0; i+1 < ARRAY_SIZE(fake_stack); i += 2) { fake_stack[i] = (uptr)&fake_stack[i+2]; // fp - fake_stack[i+1] = i+1; // retaddr + fake_stack[i+1] = PC(i + 1); // retaddr } // Mark the last fp as zero to terminate the stack trace. fake_stack[RoundDownTo(ARRAY_SIZE(fake_stack) - 1, 2)] = 0; @@ -42,7 +46,7 @@ void FastUnwindTest::SetUp() { fake_top = (uptr)&fake_stack[ARRAY_SIZE(fake_stack) + 2]; // Bottom is one slot before the start because FastUnwindStack uses >. fake_bottom = (uptr)&fake_stack[-1]; - start_pc = 0; + start_pc = PC(0); // This is common setup done by __asan::GetStackTrace(). trace.size = 0; @@ -57,7 +61,7 @@ TEST_F(FastUnwindTest, Basic) { EXPECT_EQ(6U, trace.size); EXPECT_EQ(start_pc, trace.trace[0]); for (uptr i = 1; i <= 5; i++) { - EXPECT_EQ(i*2 - 1, trace.trace[i]); + EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); } } @@ -71,8 +75,22 @@ TEST_F(FastUnwindTest, FramePointerLoop) { EXPECT_EQ(4U, trace.size); EXPECT_EQ(start_pc, trace.trace[0]); for (uptr i = 1; i <= 3; i++) { - EXPECT_EQ(i*2 - 1, trace.trace[i]); + EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); } } +TEST_F(FastUnwindTest, MisalignedFramePointer) { + // Make one fp misaligned. + fake_stack[4] += 3; + trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], + fake_top, fake_bottom); + // Should get all on-stack retaddrs up to the 4th slot and start_pc. + EXPECT_EQ(4U, trace.size); + EXPECT_EQ(start_pc, trace.trace[0]); + for (uptr i = 1; i < 4U; i++) { + EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); + } +} + + } // namespace __sanitizer