diff options
5 files changed, 25 insertions, 8 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cc b/compiler-rt/lib/sanitizer_common/sanitizer_common.cc index 8aea7bcdbcf..79fcbb1183f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cc @@ -25,13 +25,7 @@ namespace __sanitizer { const char *SanitizerToolName = "SanitizerTool"; atomic_uint32_t current_verbosity; - -uptr GetPageSizeCached() { - static uptr PageSize; - if (!PageSize) - PageSize = GetPageSize(); - return PageSize; -} +uptr PageSizeCached; StaticSpinMutex report_file_mu; ReportFile report_file = {&report_file_mu, kStderrFd, "", "", 0}; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 24ef93a9ce1..6c1d6a00a10 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -63,7 +63,12 @@ INLINE int Verbosity() { } uptr GetPageSize(); -uptr GetPageSizeCached(); +extern uptr PageSizeCached; +INLINE uptr GetPageSizeCached() { + if (!PageSizeCached) + PageSizeCached = GetPageSize(); + return PageSizeCached; +} uptr GetMmapGranularity(); uptr GetMaxVirtualAddress(); // Threads diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc index bf5456fc277..8a3fa1c1db2 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -66,6 +66,7 @@ static inline uhwptr *GetCanonicFrame(uptr bp, void BufferedStackTrace::FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom, u32 max_depth) { + const uptr kPageSize = GetPageSizeCached(); CHECK_GE(max_depth, 2); trace_buffer[0] = pc; size = 1; @@ -92,6 +93,8 @@ void BufferedStackTrace::FastUnwindStack(uptr pc, uptr bp, uptr stack_top, #else uhwptr pc1 = frame[1]; #endif + if (pc1 < kPageSize) + break; if (pc1 != pc) { trace_buffer[size++] = (uptr) pc1; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc index f38886acd54..c9dfb8a0ead 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cc @@ -108,6 +108,8 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) { UnwindTraceArg *arg = (UnwindTraceArg*)param; CHECK_LT(arg->stack->size, arg->max_depth); uptr pc = Unwind_GetIP(ctx); + const uptr kPageSize = GetPageSizeCached(); + if (pc < kPageSize) return UNWIND_STOP; arg->stack->trace_buffer[arg->stack->size++] = pc; if (arg->stack->size == arg->max_depth) return UNWIND_STOP; return UNWIND_CONTINUE; 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 3d57eded948..ba9f4fd6932 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc @@ -136,6 +136,19 @@ TEST_F(FastUnwindTest, FPBelowPrevFP) { EXPECT_EQ(PC(1), trace.trace[1]); } +TEST_F(FastUnwindTest, CloseToZeroFrame) { + // Make one pc a NULL pointer. + fake_stack[5] = 0x0; + if (!TryFastUnwind(kStackTraceMax)) + return; + // The stack should be truncated at the NULL pointer (and not include it). + EXPECT_EQ(3U, trace.size); + EXPECT_EQ(start_pc, trace.trace[0]); + for (uptr i = 1; i < 3U; i++) { + EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); + } +} + TEST(SlowUnwindTest, ShortStackTrace) { if (StackTrace::WillUseFastUnwind(false)) return; |