Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,59 @@
// Test for threads spawned with wqthread_start
// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0"
// RUN: %clangxx_lsan %s -DDISPATCH_ASYNC -o %t-async -framework Foundation
// RUN: %clangxx_lsan %s -DDISPATCH_SYNC -o %t-sync -framework Foundation
// RUN: %env_lsan_opts=$LSAN_BASE not %run %t-async 2>&1 | FileCheck %s
// RUN: %env_lsan_opts=$LSAN_BASE not %run %t-sync 2>&1 | FileCheck %s
#include <dispatch/dispatch.h>
#include <pthread.h>
#include <stdlib.h>
#include "sanitizer_common/print_address.h"
bool done = false;
void worker_do_leak(int size) {
void *p = malloc(size);
print_address("Test alloc: ", 1, p);
done = true;
}
#if DISPATCH_ASYNC
// Tests for the Grand Central Dispatch. See
// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
// for the reference.
void TestGCDDispatch() {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_block_t block = ^{
worker_do_leak(1337);
};
// dispatch_async() runs the task on a worker thread that does not go through
// pthread_create(). We need to verify that LeakSanitizer notices that the
// thread has started.
dispatch_async(queue, block);
while (!done)
pthread_yield_np();
}
#elif DISPATCH_SYNC
void TestGCDDispatch() {
dispatch_queue_t queue = dispatch_get_global_queue(2, 0);
dispatch_block_t block = ^{
worker_do_leak(1337);
};
// dispatch_sync() runs the task on a worker thread that does not go through
// pthread_create(). We need to verify that LeakSanitizer notices that the
// thread has started.
dispatch_sync(queue, block);
}
#endif
int main() {
TestGCDDispatch();
return 0;
}
// CHECK: Test alloc: [[addr:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[addr]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:

View File

@@ -0,0 +1,9 @@
def getRoot(config):
if not config.parent:
return config
return getRoot(config.parent)
root = getRoot(config)
if root.host_os not in ['Darwin']:
config.unsupported = True

View File

@@ -0,0 +1,46 @@
// Regression test for thread lifetime tracking. Thread data should be
// considered live during the thread's termination, at least until the
// user-installed TSD destructors have finished running (since they may contain
// additional cleanup tasks). LSan doesn't actually meet that goal 100%, but it
// makes its best effort.
// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0"
// RUN: %clang_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE:use_tls=1 %run %t
// RUN: %env_lsan_opts=$LSAN_BASE:use_tls=0 not %run %t 2>&1 | FileCheck %s
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "sanitizer/lsan_interface.h"
#include "sanitizer_common/print_address.h"
pthread_key_t key;
__thread void *p;
void key_destructor(void *arg) {
// Generally this may happen on a different thread.
__lsan_do_leak_check();
}
void *thread_func(void *arg) {
p = malloc(1337);
print_address("Test alloc: ", 1, p);
int res = pthread_setspecific(key, (void*)1);
assert(res == 0);
return 0;
}
int main() {
int res = pthread_key_create(&key, &key_destructor);
assert(res == 0);
pthread_t thread_id;
res = pthread_create(&thread_id, 0, thread_func, 0);
assert(res == 0);
res = pthread_join(thread_id, 0);
assert(res == 0);
return 0;
}
// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: [[ADDR]] (1337 bytes)

View File

@@ -0,0 +1,39 @@
// Regression test. Disabler should not depend on TSD validity.
// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=1:use_ld_allocations=0"
// RUN: %clang_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE %run %t
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "sanitizer/lsan_interface.h"
pthread_key_t key;
void key_destructor(void *arg) {
__lsan_disable();
void *p = malloc(1337);
// Break optimization.
fprintf(stderr, "Test alloc: %p.\n", p);
pthread_setspecific(key, 0);
__lsan_enable();
}
void *thread_func(void *arg) {
int res = pthread_setspecific(key, (void*)1);
assert(res == 0);
return 0;
}
int main() {
int res = pthread_key_create(&key, &key_destructor);
assert(res == 0);
pthread_t thread_id;
res = pthread_create(&thread_id, 0, thread_func, 0);
assert(res == 0);
res = pthread_join(thread_id, 0);
assert(res == 0);
return 0;
}

View File

@@ -0,0 +1,24 @@
// Test that thread local data is handled correctly after forking without exec().
// RUN: %clangxx_lsan %s -o %t
// RUN: %run %t 2>&1
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
__thread void *thread_local_var;
int main() {
int status = 0;
thread_local_var = malloc(1337);
pid_t pid = fork();
assert(pid >= 0);
if (pid > 0) {
waitpid(pid, &status, 0);
assert(WIFEXITED(status));
return WEXITSTATUS(status);
}
return 0;
}

View File

@@ -0,0 +1,43 @@
// Test that thread local data is handled correctly after forking without
// exec(). In this test leak checking is initiated from a non-main thread.
// RUN: %clangxx_lsan %s -o %t
// RUN: %run %t 2>&1
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
__thread void *thread_local_var;
void *exit_thread_func(void *arg) {
exit(0);
}
void ExitFromThread() {
pthread_t tid;
int res;
res = pthread_create(&tid, 0, exit_thread_func, 0);
assert(res == 0);
pthread_join(tid, 0);
}
int main() {
int status = 0;
thread_local_var = malloc(1337);
pid_t pid = fork();
assert(pid >= 0);
if (pid > 0) {
waitpid(pid, &status, 0);
assert(WIFEXITED(status));
return WEXITSTATUS(status);
} else {
// Spawn a thread and call exit() from there, to check that we track main
// thread's pid correctly even if leak checking is initiated from another
// thread.
ExitFromThread();
}
return 0;
}

View File

@@ -0,0 +1,61 @@
// Check that if LSan finds that SP doesn't point into thread stack (e.g.
// if swapcontext is used), LSan will not hit the guard page.
// RUN: %clang_lsan %s -o %t && %run %t
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <ucontext.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int ctxfunc_started = 0;
static void die(const char* msg, int err) {
if (err == 0)
err = errno;
fprintf(stderr, "%s: %s\n", msg, strerror(err));
exit(EXIT_FAILURE);
}
static void ctxfunc() {
pthread_mutex_lock(&mutex);
ctxfunc_started = 1;
// printf("ctxfunc\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
// Leave this context alive when the program exits.
for (;;);
}
static void* thread(void* arg) {
(void)arg;
ucontext_t ctx;
void* stack;
if (getcontext(&ctx) < 0)
die("getcontext", 0);
stack = malloc(1 << 11);
if (stack == NULL)
die("malloc", 0);
ctx.uc_stack.ss_sp = stack;
ctx.uc_stack.ss_size = 1 << 11;
makecontext(&ctx, ctxfunc, 0);
setcontext(&ctx);
die("setcontext", 0);
return NULL;
}
int main() {
pthread_t tid;
int i;
pthread_mutex_lock(&mutex);
i = pthread_create(&tid, NULL, thread, NULL);
if (i != 0)
die("pthread_create", i);
while (!ctxfunc_started) pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
return 0;
}

View File

@@ -0,0 +1,9 @@
def getRoot(config):
if not config.parent:
return config
return getRoot(config.parent)
root = getRoot(config)
if root.host_os not in ['Linux']:
config.unsupported = True

View File

@@ -0,0 +1,52 @@
// Test that dynamically allocated TLS space is included in the root set.
// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0:use_ld_allocations=0"
// RUN: %clangxx %s -DBUILD_DSO -fPIC -shared -o %t-so.so
// RUN: %clangxx_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1
// RUN: %env_lsan_opts="" %run %t 2>&1
// UNSUPPORTED: i386-linux,arm
#ifndef BUILD_DSO
#include <assert.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "sanitizer_common/print_address.h"
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);
// If we don't know about dynamic TLS, we will return a false leak above.
void **p_in_tls = StoreToTLS(p);
assert(*p_in_tls == p);
print_address("Test alloc: ", 1, p);
return 0;
}
// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
#else // BUILD_DSO
// 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];
}
#endif // BUILD_DSO

View File

@@ -0,0 +1,38 @@
// Test that dynamically allocated thread-specific storage is included in the root set.
// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0"
// RUN: %clangxx_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1
// RUN: %env_lsan_opts="" %run %t 2>&1
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "sanitizer_common/print_address.h"
// 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);
print_address("Test alloc: ", 1, p);
return 0;
}
// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:

View File

@@ -0,0 +1,32 @@
// Test that statically allocated thread-specific storage is included in the root set.
// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0"
// RUN: %clangxx_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1
// RUN: %env_lsan_opts="" %run %t 2>&1
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "sanitizer_common/print_address.h"
// 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);
print_address("Test alloc: ", 1, p);
return 0;
}
// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:

View File

@@ -0,0 +1,22 @@
// Test that statically allocated TLS space is included in the root set.
// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0"
// RUN: %clangxx_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1
// RUN: %env_lsan_opts="" %run %t 2>&1
#include <stdio.h>
#include <stdlib.h>
#include "sanitizer_common/print_address.h"
__thread void *tls_var;
int main() {
tls_var = malloc(1337);
print_address("Test alloc: ", 1, tls_var);
return 0;
}
// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:

View File

@@ -0,0 +1,131 @@
// Test the behavior of malloc/calloc/realloc/new when the allocation size is
// more than LSan allocator's max allowed one.
// By default (allocator_may_return_null=0) the process should crash.
// With allocator_may_return_null=1 the allocator should return 0, except the
// operator new(), which should crash anyway (operator new(std::nothrow) should
// return nullptr, indeed).
//
// RUN: %clangxx_lsan -O0 %s -o %t
// RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH
// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-mCRASH
// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t malloc 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-mNULL
// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-cCRASH
// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t calloc 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-cNULL
// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-coCRASH
// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t calloc-overflow 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-coNULL
// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-rCRASH
// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t realloc 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-rNULL
// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-mrCRASH
// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t realloc-after-malloc 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-mrNULL
// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t new 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH
// RUN: %env_lsan_opts=allocator_may_return_null=1 not %run %t new 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH
// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH
// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-nnNULL
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits>
#include <new>
int main(int argc, char **argv) {
// Disable stderr buffering. Needed on Windows.
setvbuf(stderr, NULL, _IONBF, 0);
assert(argc == 2);
const char *action = argv[1];
fprintf(stderr, "%s:\n", action);
// Use max of ASan and LSan allocator limits to cover both "lsan" and
// "lsan + asan" configs.
static const size_t kMaxAllowedMallocSizePlusOne =
#if __LP64__ || defined(_WIN64)
(1ULL << 40) + 1;
#else
(3UL << 30) + 1;
#endif
void *x = 0;
if (!strcmp(action, "malloc")) {
x = malloc(kMaxAllowedMallocSizePlusOne);
} else if (!strcmp(action, "calloc")) {
x = calloc((kMaxAllowedMallocSizePlusOne / 4) + 1, 4);
} else if (!strcmp(action, "calloc-overflow")) {
volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max();
size_t kArraySize = 4096;
volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
x = calloc(kArraySize, kArraySize2);
} else if (!strcmp(action, "realloc")) {
x = realloc(0, kMaxAllowedMallocSizePlusOne);
} else if (!strcmp(action, "realloc-after-malloc")) {
char *t = (char*)malloc(100);
*t = 42;
x = realloc(t, kMaxAllowedMallocSizePlusOne);
assert(*t == 42);
free(t);
} else if (!strcmp(action, "new")) {
x = operator new(kMaxAllowedMallocSizePlusOne);
} else if (!strcmp(action, "new-nothrow")) {
x = operator new(kMaxAllowedMallocSizePlusOne, std::nothrow);
} else {
assert(0);
}
fprintf(stderr, "errno: %d\n", errno);
// The NULL pointer is printed differently on different systems, while (long)0
// is always the same.
fprintf(stderr, "x: %zu\n", (size_t)x);
free(x);
return x != 0;
}
// CHECK-mCRASH: malloc:
// CHECK-mCRASH: Sanitizer's allocator is terminating the process
// CHECK-cCRASH: calloc:
// CHECK-cCRASH: Sanitizer's allocator is terminating the process
// CHECK-coCRASH: calloc-overflow:
// CHECK-coCRASH: Sanitizer's allocator is terminating the process
// CHECK-rCRASH: realloc:
// CHECK-rCRASH: Sanitizer's allocator is terminating the process
// CHECK-mrCRASH: realloc-after-malloc:
// CHECK-mrCRASH: Sanitizer's allocator is terminating the process
// CHECK-nCRASH: new:
// CHECK-nCRASH: Sanitizer's allocator is terminating the process
// CHECK-nnCRASH: new-nothrow:
// CHECK-nnCRASH: Sanitizer's allocator is terminating the process
// CHECK-mNULL: malloc:
// CHECK-mNULL: errno: 12
// CHECK-mNULL: x: 0
// CHECK-cNULL: calloc:
// CHECK-cNULL: errno: 12
// CHECK-cNULL: x: 0
// CHECK-coNULL: calloc-overflow:
// CHECK-coNULL: errno: 12
// CHECK-coNULL: x: 0
// CHECK-rNULL: realloc:
// CHECK-rNULL: errno: 12
// CHECK-rNULL: x: 0
// CHECK-mrNULL: realloc-after-malloc:
// CHECK-mrNULL: errno: 12
// CHECK-mrNULL: x: 0
// CHECK-nnNULL: new-nothrow:
// CHECK-nnNULL: x: 0

View File

@@ -0,0 +1,11 @@
// RUN: %clangxx_lsan -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
extern "C"
const char *__lsan_default_options() {
// CHECK: Available flags for {{Leak|Address}}Sanitizer:
return "verbosity=1 help=1";
}
int main() {
return 0;
}

View File

@@ -0,0 +1,24 @@
// Test for __lsan_disable() / __lsan_enable().
// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0"
// RUN: %clang_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck %s
#include <stdio.h>
#include <stdlib.h>
#include "sanitizer/lsan_interface.h"
int main() {
void **p;
{
__lsan_disable();
p = malloc(sizeof(void *));
__lsan_enable();
}
*p = malloc(666);
void *q = malloc(1337);
// Break optimization.
fprintf(stderr, "Test alloc: %p.\n", q);
return 0;
}
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: 1337 byte(s) leaked in 1 allocation(s)

View File

@@ -0,0 +1,25 @@
// Test for ScopedDisabler.
// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0"
// RUN: %clangxx_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck %s
#include <stdio.h>
#include <stdlib.h>
#include "sanitizer/lsan_interface.h"
int main() {
void **p;
{
__lsan::ScopedDisabler d;
p = new void *;
fprintf(stderr, "Test alloc p: %p.\n", p);
}
*p = malloc(666);
void *q = malloc(1337);
fprintf(stderr, "Test alloc q: %p.\n", q);
return 0;
}
// CHECK: Test alloc p: [[ADDR:.*]].
// CHECK-NOT: [[ADDR]]

View File

@@ -0,0 +1,36 @@
// Test for __lsan_do_leak_check(). We test it by making the leak check run
// before global destructors, which also tests compatibility with HeapChecker's
// "normal" mode (LSan runs in "strict" mode by default).
// RUN: LSAN_BASE="use_stacks=0:use_registers=0"
// RUN: %clangxx_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck --check-prefix=CHECK-strict %s
// RUN: %env_lsan_opts=$LSAN_BASE not %run %t foo 2>&1 | FileCheck --check-prefix=CHECK-normal %s
#include <stdio.h>
#include <stdlib.h>
#include <sanitizer/lsan_interface.h>
struct LeakyGlobal {
LeakyGlobal() {
p = malloc(1337);
}
~LeakyGlobal() {
p = 0;
}
void *p;
};
LeakyGlobal leaky_global;
int main(int argc, char *argv[]) {
// Register leak check to run before global destructors.
if (argc > 1)
atexit(&__lsan_do_leak_check);
void *p = malloc(666);
printf("Test alloc: %p\n", p);
printf("Test alloc in leaky global: %p\n", leaky_global.p);
return 0;
}
// CHECK-strict: SUMMARY: {{(Leak|Address)}}Sanitizer: 2003 byte(s) leaked in 2 allocation(s)
// CHECK-normal: SUMMARY: {{(Leak|Address)}}Sanitizer: 666 byte(s) leaked in 1 allocation(s)

View File

@@ -0,0 +1,49 @@
// A benchmark that executes malloc/free pairs in parallel.
// Usage: ./a.out number_of_threads total_number_of_allocations
// RUN: LSAN_BASE="use_ld_allocations=0"
// RUN: %clangxx_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE %run %t 5 1000000 2>&1
#include <assert.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
int num_threads;
int total_num_alloc;
const int kMaxNumThreads = 5000;
pthread_t tid[kMaxNumThreads];
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
bool go = false;
void *thread_fun(void *arg) {
pthread_mutex_lock(&mutex);
while (!go) pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
for (int i = 0; i < total_num_alloc / num_threads; i++) {
void *p = malloc(10);
__asm__ __volatile__("" : : "r"(p) : "memory");
free((void *)p);
}
return 0;
}
int main(int argc, char** argv) {
assert(argc == 3);
num_threads = atoi(argv[1]);
assert(num_threads > 0);
assert(num_threads <= kMaxNumThreads);
total_num_alloc = atoi(argv[2]);
assert(total_num_alloc > 0);
printf("%d threads, %d allocations in each\n", num_threads,
total_num_alloc / num_threads);
for (int i = 0; i < num_threads; i++)
pthread_create(&tid[i], 0, thread_fun, 0);
pthread_mutex_lock(&mutex);
go = true;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
for (int i = 0; i < num_threads; i++) pthread_join(tid[i], 0);
return 0;
}

View File

@@ -0,0 +1,23 @@
// Test for __lsan_ignore_object().
// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0"
// RUN: %clang_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck %s
#include <stdio.h>
#include <stdlib.h>
#include "sanitizer/lsan_interface.h"
int main() {
// Explicitly ignored object.
void **p = malloc(sizeof(void *));
// Transitively ignored object.
*p = malloc(666);
// Non-ignored object.
volatile void *q = malloc(1337);
fprintf(stderr, "Test alloc: %p.\n", p);
__lsan_ignore_object(p);
return 0;
}
// CHECK: Test alloc: [[ADDR:.*]].
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: 1337 byte(s) leaked in 1 allocation(s)

View File

@@ -0,0 +1,20 @@
// Test for incorrect use of __lsan_ignore_object().
// RUN: %clangxx_lsan %s -o %t
// RUN: %env_lsan_opts=$LSAN_BASE %run %t 2>&1 | FileCheck %s
#include <stdio.h>
#include <stdlib.h>
#include "sanitizer/lsan_interface.h"
int main() {
void *p = malloc(1337);
fprintf(stderr, "Test alloc: %p.\n", p);
__lsan_ignore_object(p);
__lsan_ignore_object(p);
free(p);
__lsan_ignore_object(p);
return 0;
}
// CHECK: Test alloc: [[ADDR:.*]].
// CHECK-NOT: SUMMARY: {{.*}} leaked

Some files were not shown because too many files have changed in this diff Show More