diff options
Diffstat (limited to 'compiler-rt/lib/lsan')
| -rw-r--r-- | compiler-rt/lib/lsan/lit_tests/TestCases/use_after_return.cc | 23 | ||||
| -rw-r--r-- | compiler-rt/lib/lsan/lsan_common.cc | 6 | ||||
| -rw-r--r-- | compiler-rt/lib/lsan/lsan_common.h | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/lsan/lsan_thread.cc | 4 |
4 files changed, 35 insertions, 0 deletions
diff --git a/compiler-rt/lib/lsan/lit_tests/TestCases/use_after_return.cc b/compiler-rt/lib/lsan/lit_tests/TestCases/use_after_return.cc new file mode 100644 index 00000000000..7ccbe43585f --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/TestCases/use_after_return.cc @@ -0,0 +1,23 @@ +// Test that fake stack (introduced by ASan's use-after-return mode) is included +// in the root set. +// RUN: LSAN_BASE="report_objects=1:use_registers=0" +// RUN: %clangxx_lsan %s -O2 -o %t +// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:detect_stack_use_after_return=1 LSAN_OPTIONS=$LSAN_BASE:"use_stacks=0" not %t 2>&1 | FileCheck %s +// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:detect_stack_use_after_return=1 LSAN_OPTIONS=$LSAN_BASE:"use_stacks=1" %t 2>&1 +// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:detect_stack_use_after_return=1 LSAN_OPTIONS="" %t 2>&1 + +#include <stdio.h> +#include <stdlib.h> + +int main() { + void *stack_var = malloc(1337); + fprintf(stderr, "Test alloc: %p.\n", stack_var); + // Take pointer to variable, to ensure it's not optimized into a register. + fprintf(stderr, "Stack var at: %p.\n", &stack_var); + // Do not return from main to prevent the pointer from going out of scope. + exit(0); +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: Directly leaked 1337 byte object at [[ADDR]] +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/lsan/lsan_common.cc b/compiler-rt/lib/lsan/lsan_common.cc index 416828ab8a2..a58e604fbcb 100644 --- a/compiler-rt/lib/lsan/lsan_common.cc +++ b/compiler-rt/lib/lsan/lsan_common.cc @@ -151,6 +151,11 @@ void ScanRangeForPointers(uptr begin, uptr end, } } +void ForEachExtraStackRangeCb(uptr begin, uptr end, void* arg) { + Frontier *frontier = reinterpret_cast<Frontier *>(arg); + ScanRangeForPointers(begin, end, frontier, "FAKE STACK", kReachable); +} + // Scans thread data (stacks and TLS) for heap pointers. static void ProcessThreads(SuspendedThreadsList const &suspended_threads, Frontier *frontier) { @@ -199,6 +204,7 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads, } ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK", kReachable); + ForEachExtraStackRange(os_id, ForEachExtraStackRangeCb, frontier); } if (flags()->use_tls) { diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index 971f7486cb3..d490f8bafd9 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -135,6 +135,8 @@ void UnlockThreadRegistry(); bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, uptr *tls_begin, uptr *tls_end, uptr *cache_begin, uptr *cache_end); +void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback, + void *arg); // If called from the main thread, updates the main thread's TID in the thread // registry. We need this to handle processes that fork() without a subsequent // exec(), which invalidates the recorded TID. To update it, we must call diff --git a/compiler-rt/lib/lsan/lsan_thread.cc b/compiler-rt/lib/lsan/lsan_thread.cc index 3bfccdf712d..0f8efc093b5 100644 --- a/compiler-rt/lib/lsan/lsan_thread.cc +++ b/compiler-rt/lib/lsan/lsan_thread.cc @@ -145,6 +145,10 @@ bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, return true; } +void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback, + void *arg) { +} + void LockThreadRegistry() { thread_registry->Lock(); } |

