From e6154323132a29f82bef72127241c5ce7e502042 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Wed, 29 May 2013 10:12:37 +0000 Subject: [PATCH] [lsan] Convert the remaining LSan tests to output tests. llvm-svn: 182839 --- .../lit_tests/SharedLibs/huge_tls_lib_so.cc | 12 +++++ .../lsan/lit_tests/large_allocation_leak.cc | 18 +++++++ .../lib/lsan/lit_tests/stale_stack_leak.cc | 42 +++++++++++++++ .../lit_tests/use_globals_uninitialized.cc | 21 ++++++++ .../lib/lsan/lit_tests/use_registers.cc | 51 +++++++++++++++++++ compiler-rt/lib/lsan/lit_tests/use_stacks.cc | 20 ++++++++ .../lib/lsan/lit_tests/use_stacks_threaded.cc | 36 +++++++++++++ .../lib/lsan/lit_tests/use_tls_dynamic.cc | 33 ++++++++++++ .../use_tls_pthread_specific_dynamic.cc | 37 ++++++++++++++ .../use_tls_pthread_specific_static.cc | 31 +++++++++++ .../lib/lsan/lit_tests/use_tls_static.cc | 21 ++++++++ .../lib/lsan/lit_tests/use_unaligned.cc | 23 +++++++++ .../sanitizer_common/scripts/check_lint.sh | 3 +- 13 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 compiler-rt/lib/lsan/lit_tests/SharedLibs/huge_tls_lib_so.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/large_allocation_leak.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/stale_stack_leak.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/use_globals_uninitialized.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/use_registers.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/use_stacks.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/use_stacks_threaded.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/use_tls_dynamic.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/use_tls_pthread_specific_dynamic.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/use_tls_pthread_specific_static.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/use_tls_static.cc create mode 100644 compiler-rt/lib/lsan/lit_tests/use_unaligned.cc diff --git a/compiler-rt/lib/lsan/lit_tests/SharedLibs/huge_tls_lib_so.cc b/compiler-rt/lib/lsan/lit_tests/SharedLibs/huge_tls_lib_so.cc new file mode 100644 index 000000000000..475a66ec12a4 --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/SharedLibs/huge_tls_lib_so.cc @@ -0,0 +1,12 @@ +// A loadable module with a large thread local section, which would require +// allocation of a new TLS storage chunk when loaded with dlopen(). We use it +// to test the reachability of such chunks in LSan tests. + +// This must be large enough that it doesn't fit into preallocated static TLS +// space (see STATIC_TLS_SURPLUS in glibc). +__thread void *huge_thread_local_array[(1 << 20) / sizeof(void *)]; // NOLINT + +extern "C" void **StoreToTLS(void *p) { + huge_thread_local_array[0] = p; + return &huge_thread_local_array[0]; +} diff --git a/compiler-rt/lib/lsan/lit_tests/large_allocation_leak.cc b/compiler-rt/lib/lsan/lit_tests/large_allocation_leak.cc new file mode 100644 index 000000000000..6db841ee5b08 --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/large_allocation_leak.cc @@ -0,0 +1,18 @@ +// Test that LargeMmapAllocator's chunks aren't reachable via some internal data structure. +// RUN: LSAN_BASE="report_blocks=1:use_stacks=0:use_registers=0" +// RUN: %clangxx_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE %t 2>&1 | FileCheck %s + +#include +#include + +int main() { + // maxsize in primary allocator is always less than this (1 << 25). + void *large_alloc = malloc(33554432); + fprintf(stderr, "Test alloc: %p.\n", large_alloc); + return 0; +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: Directly leaked 33554432 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/lsan/lit_tests/stale_stack_leak.cc b/compiler-rt/lib/lsan/lit_tests/stale_stack_leak.cc new file mode 100644 index 000000000000..5d57082c42cd --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/stale_stack_leak.cc @@ -0,0 +1,42 @@ +// Test that out-of-scope local variables are ignored by LSan. +// RUN: LSAN_BASE="report_blocks=1:use_registers=0:use_stacks=1" +// RUN: %clangxx_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE":exitcode=0" %t 2>&1 | FileCheck --check-prefix=CHECK-sanity %s + +#include +#include + +void **pp; + +// Put pointer far enough on the stack that LSan has space to run in without +// overwriting it. +// Hopefully the argument p will be passed on a register, saving us from false +// negatives. +__attribute__((noinline)) +void *PutPointerOnStaleStack(void *p) { + void *locals[2048]; + locals[0] = p; + pp = &locals[0]; + fprintf(stderr, "Test alloc: %p.\n", locals[0]); + return 0; +} + +int main() { + PutPointerOnStaleStack(malloc(1337)); + return 0; +} + +// This must run after LSan, to ensure LSan didn't overwrite the pointer before +// it had a chance to see it. If LSan is invoked with atexit(), this works. +// Otherwise, we need a different method. +__attribute__((destructor)) +void ConfirmPointerHasSurvived() { + fprintf(stderr, "Value after LSan: %p.\n", *pp); +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK-sanity: Test alloc: [[ADDR:.*]]. +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: Directly leaked 1337 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: +// CHECK-sanity: Value after LSan: [[ADDR]]. diff --git a/compiler-rt/lib/lsan/lit_tests/use_globals_uninitialized.cc b/compiler-rt/lib/lsan/lit_tests/use_globals_uninitialized.cc new file mode 100644 index 000000000000..d383128659d4 --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/use_globals_uninitialized.cc @@ -0,0 +1,21 @@ +// Test that uninitialized globals are included in the root set. +// RUN: LSAN_BASE="report_blocks=1:use_stacks=0:use_registers=0" +// RUN: %clangxx_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_globals=0" %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_globals=1" %t 2>&1 +// RUN: LSAN_OPTIONS="" %t 2>&1 + +#include +#include + +void *bss_var; + +int main() { + bss_var = malloc(1337); + fprintf(stderr, "Test alloc: %p.\n", bss_var); + return 0; +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: Directly leaked 1337 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/lsan/lit_tests/use_registers.cc b/compiler-rt/lib/lsan/lit_tests/use_registers.cc new file mode 100644 index 000000000000..4b29a847acb8 --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/use_registers.cc @@ -0,0 +1,51 @@ +// Test that registers of running threads are included in the root set. +// RUN: LSAN_BASE="report_blocks=1:use_stacks=0" +// RUN: %clangxx_lsan -pthread %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_registers=0" %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_registers=1" %t 2>&1 +// RUN: LSAN_OPTIONS="" %t 2>&1 + +#include +#include +#include +#include + +extern "C" +void *registers_thread_func(void *arg) { + int *sync = reinterpret_cast(arg); + void *p = malloc(1337); + // To store the pointer, choose a register which is unlikely to be reused by + // a function call. +#if defined(__i386__) + asm ( "mov %0, %%esi" + : + : "r" (p) + ); +#elif defined(__x86_64__) + asm ( "mov %0, %%r15" + : + : "r" (p) + ); +#else +#error "Test is not supported on this architecture." +#endif + fprintf(stderr, "Test alloc: %p.\n", p); + fflush(stderr); + __sync_fetch_and_xor(sync, 1); + while (true) + pthread_yield(); +} + +int main() { + int sync = 0; + pthread_t thread_id; + int res = pthread_create(&thread_id, 0, registers_thread_func, &sync); + assert(res == 0); + while (!__sync_fetch_and_xor(&sync, 0)) + pthread_yield(); + return 0; +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: Directly leaked 1337 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/lsan/lit_tests/use_stacks.cc b/compiler-rt/lib/lsan/lit_tests/use_stacks.cc new file mode 100644 index 000000000000..e06a7a4788cc --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/use_stacks.cc @@ -0,0 +1,20 @@ +// Test that stack of main thread is included in the root set. +// RUN: LSAN_BASE="report_blocks=1:use_registers=0" +// RUN: %clangxx_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_stacks=0" %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_stacks=1" %t 2>&1 +// RUN: LSAN_OPTIONS="" %t 2>&1 + +#include +#include + +int main() { + void *stack_var = malloc(1337); + fprintf(stderr, "Test alloc: %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: LeakSanitizer: detected memory leaks +// CHECK: Directly leaked 1337 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/lsan/lit_tests/use_stacks_threaded.cc b/compiler-rt/lib/lsan/lit_tests/use_stacks_threaded.cc new file mode 100644 index 000000000000..efce855bdea4 --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/use_stacks_threaded.cc @@ -0,0 +1,36 @@ +// Test that stacks of non-main threads are included in the root set. +// RUN: LSAN_BASE="report_blocks=1:use_registers=0" +// RUN: %clangxx_lsan -pthread %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_stacks=0" %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_stacks=1" %t 2>&1 +// RUN: LSAN_OPTIONS="" %t 2>&1 + +#include +#include +#include +#include + +extern "C" +void *stacks_thread_func(void *arg) { + int *sync = reinterpret_cast(arg); + void *p = malloc(1337); + fprintf(stderr, "Test alloc: %p.\n", p); + fflush(stderr); + __sync_fetch_and_xor(sync, 1); + while (true) + pthread_yield(); +} + +int main() { + int sync = 0; + pthread_t thread_id; + int res = pthread_create(&thread_id, 0, stacks_thread_func, &sync); + assert(res == 0); + while (!__sync_fetch_and_xor(&sync, 0)) + pthread_yield(); + return 0; +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: Directly leaked 1337 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/lsan/lit_tests/use_tls_dynamic.cc b/compiler-rt/lib/lsan/lit_tests/use_tls_dynamic.cc new file mode 100644 index 000000000000..c97a1ea95b3b --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/use_tls_dynamic.cc @@ -0,0 +1,33 @@ +// Test that dynamically allocated TLS space is included in the root set. +// RUN: LSAN_BASE="report_blocks=1:use_stacks=0:use_registers=0" +// RUN: %clangxx %p/SharedLibs/huge_tls_lib_so.cc -fPIC -shared -o %t-so.so +// RUN: %clangxx_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=0" %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=1" %t 2>&1 +// RUN: LSAN_OPTIONS="" %t 2>&1 + +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + std::string path = std::string(argv[0]) + "-so.so"; + + void *handle = dlopen(path.c_str(), RTLD_LAZY); + assert(handle != 0); + typedef void **(* store_t)(void *p); + store_t StoreToTLS = (store_t)dlsym(handle, "StoreToTLS"); + assert(dlerror() == 0); + + void *p = malloc(1337); + void **p_in_tls = StoreToTLS(p); + assert(*p_in_tls == p); + fprintf(stderr, "Test alloc: %p.\n", p); + return 0; +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: leaked 1337 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/lsan/lit_tests/use_tls_pthread_specific_dynamic.cc b/compiler-rt/lib/lsan/lit_tests/use_tls_pthread_specific_dynamic.cc new file mode 100644 index 000000000000..a8fd061dc11c --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/use_tls_pthread_specific_dynamic.cc @@ -0,0 +1,37 @@ +// Test that dynamically allocated thread-specific storage is included in the root set. +// RUN: LSAN_BASE="report_blocks=1:use_stacks=0:use_registers=0" +// RUN: %clangxx_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=0" %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=1" %t 2>&1 +// RUN: LSAN_OPTIONS="" %t 2>&1 + +#include +#include +#include +#include + +// From glibc: this many keys are stored in the thread descriptor directly. +const unsigned PTHREAD_KEY_2NDLEVEL_SIZE = 32; + +int main() { + static const unsigned kDummyKeysCount = PTHREAD_KEY_2NDLEVEL_SIZE; + int res; + pthread_key_t dummy_keys[kDummyKeysCount]; + for (unsigned i = 0; i < kDummyKeysCount; i++) { + res = pthread_key_create(&dummy_keys[i], NULL); + assert(res == 0); + } + pthread_key_t key; + res = pthread_key_create(&key, NULL); + assert(key >= PTHREAD_KEY_2NDLEVEL_SIZE); + assert(res == 0); + void *p = malloc(1337); + res = pthread_setspecific(key, p); + assert(res == 0); + fprintf(stderr, "Test alloc: %p.\n", p); + return 0; +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: leaked 1337 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/lsan/lit_tests/use_tls_pthread_specific_static.cc b/compiler-rt/lib/lsan/lit_tests/use_tls_pthread_specific_static.cc new file mode 100644 index 000000000000..b28406c5323a --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/use_tls_pthread_specific_static.cc @@ -0,0 +1,31 @@ +// Test that statically allocated thread-specific storage is included in the root set. +// RUN: LSAN_BASE="report_blocks=1:use_stacks=0:use_registers=0" +// RUN: %clangxx_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=0" %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=1" %t 2>&1 +// RUN: LSAN_OPTIONS="" %t 2>&1 + +#include +#include +#include +#include + +// From glibc: this many keys are stored in the thread descriptor directly. +const unsigned PTHREAD_KEY_2NDLEVEL_SIZE = 32; + +int main() { + pthread_key_t key; + int res; + res = pthread_key_create(&key, NULL); + assert(res == 0); + assert(key < PTHREAD_KEY_2NDLEVEL_SIZE); + void *p = malloc(1337); + res = pthread_setspecific(key, p); + assert(res == 0); + fprintf(stderr, "Test alloc: %p.\n", p); + return 0; +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: Directly leaked 1337 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/lsan/lit_tests/use_tls_static.cc b/compiler-rt/lib/lsan/lit_tests/use_tls_static.cc new file mode 100644 index 000000000000..a4d12f8a9782 --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/use_tls_static.cc @@ -0,0 +1,21 @@ +// Test that statically allocated TLS space is included in the root set. +// RUN: LSAN_BASE="report_blocks=1:use_stacks=0:use_registers=0" +// RUN: %clangxx_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=0" %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_tls=1" %t 2>&1 +// RUN: LSAN_OPTIONS="" %t 2>&1 + +#include +#include + +__thread void *tls_var; + +int main() { + tls_var = malloc(1337); + fprintf(stderr, "Test alloc: %p.\n", tls_var); + return 0; +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: Directly leaked 1337 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/lsan/lit_tests/use_unaligned.cc b/compiler-rt/lib/lsan/lit_tests/use_unaligned.cc new file mode 100644 index 000000000000..75b90d60bd76 --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/use_unaligned.cc @@ -0,0 +1,23 @@ +// Test that unaligned pointers are detected correctly. +// RUN: LSAN_BASE="report_blocks=1:use_stacks=0:use_registers=0" +// RUN: %clangxx_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_unaligned=0" %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_unaligned=1" %t 2>&1 + +#include +#include +#include + +void *arr[2]; + +int main() { + void *p = malloc(1337); + fprintf(stderr, "Test alloc: %p.\n", p); + char *char_arr = (char *)arr; + memcpy(char_arr + 1, &p, sizeof(p)); + return 0; +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: Directly leaked 1337 byte block at [[ADDR]] +// CHECK: SUMMARY: LeakSanitizer: diff --git a/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh b/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh index 3240f6f18cee..bd0661ca2174 100755 --- a/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh +++ b/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh @@ -80,7 +80,8 @@ ${CPPLINT} --filter=${MSAN_RTL_LINT_FILTER} ${MSAN_RTL}/*.{cc,h} LSAN_RTL=${COMPILER_RT}/lib/lsan ${CPPLINT} --filter=${LSAN_RTL_LINT_FILTER} ${LSAN_RTL}/*.{cc,h} ${CPPLINT} --filter=${LSAN_RTL_LINT_FILTER} ${LSAN_RTL}/tests/*.{cc,h} -${CPPLINT} --filter=${LSAN_LIT_TEST_LINT_FILTER} ${LSAN_RTL}/lit_tests/*.{cc,h} +${CPPLINT} --filter=${LSAN_LIT_TEST_LINT_FILTER} ${LSAN_RTL}/lit_tests/*.{cc,h} \ + ${LSAN_RTL}/lit_tests/*/*.cc set +e