diff --git a/compiler-rt/lib/hwasan/hwasan.cpp b/compiler-rt/lib/hwasan/hwasan.cpp --- a/compiler-rt/lib/hwasan/hwasan.cpp +++ b/compiler-rt/lib/hwasan/hwasan.cpp @@ -86,8 +86,7 @@ cf.clear_shadow_mmap_threshold = 4096 * (SANITIZER_ANDROID ? 2 : 8); // Sigtrap is used in error reporting. cf.handle_sigtrap = kHandleSignalExclusive; - // FIXME: enable once all false positives have been fixed. - cf.detect_leaks = false; + cf.detect_leaks = true; #if SANITIZER_ANDROID // Let platform handle other signals. It is better at reporting them then we diff --git a/compiler-rt/test/hwasan/TestCases/Linux/leak_check_segv.cpp b/compiler-rt/test/hwasan/TestCases/Linux/leak_check_segv.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/Linux/leak_check_segv.cpp @@ -0,0 +1,23 @@ +// Test that SIGSEGV during leak checking does not crash the process. +// RUN: %clangxx_hwasan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s +// REQUIRES: leak-detection +#include +#include +#include +#include + +char data[10 * 1024 * 1024]; + +int main() { + void *p = malloc(10 * 1024 * 1024); + // surprise-surprise! + mprotect((void*)(((unsigned long)p + 4095) & ~4095), 16 * 1024, PROT_NONE); + mprotect((void*)(((unsigned long)data + 4095) & ~4095), 16 * 1024, PROT_NONE); + __lsan_do_leak_check(); + fprintf(stderr, "DONE\n"); +} + +// CHECK: Tracer caught signal 11 +// CHECK: LeakSanitizer has encountered a fatal error +// CHECK: HINT: For debugging, try setting {{.*}} LSAN_OPTIONS +// CHECK-NOT: DONE diff --git a/compiler-rt/test/hwasan/TestCases/Linux/signal_during_stop_the_world.cpp b/compiler-rt/test/hwasan/TestCases/Linux/signal_during_stop_the_world.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/Linux/signal_during_stop_the_world.cpp @@ -0,0 +1,60 @@ +// Test StopTheWorld behavior during signal storm. +// Historically StopTheWorld crashed because did not handle EINTR properly. +// The test is somewhat convoluted, but that's what caused crashes previously. + +// RUN: %clangxx_hwasan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void handler(int signo); +static void *thr(void *arg); + +int main() { + struct sigaction act = {}; + act.sa_handler = handler; + sigaction(SIGPROF, &act, 0); + + pid_t pid = fork(); + if (pid < 0) { + fprintf(stderr, "failed to fork\n"); + exit(1); + } + if (pid == 0) { + // Child constantly sends signals to parent to cause spurious return from + // waitpid in StopTheWorld. + prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); + pid_t parent = getppid(); + for (;;) { + // There is no strong reason for these two particular signals, + // but at least one of them ought to unblock waitpid. + kill(parent, SIGCHLD); + kill(parent, SIGPROF); + } + } + usleep(10000); // Let the child start. + __lsan_do_leak_check(); + // Kill and join the child. + kill(pid, SIGTERM); + waitpid(pid, 0, 0); + sleep(1); // If the tracer thread still runs, give it time to crash. + fprintf(stderr, "DONE\n"); +// CHECK: DONE +} + +static void handler(int signo) { +} + +static void *thr(void *arg) { + for (;;) + sleep(1); + return 0; +} diff --git a/compiler-rt/test/hwasan/TestCases/lsan_annotations.cpp b/compiler-rt/test/hwasan/TestCases/lsan_annotations.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/lsan_annotations.cpp @@ -0,0 +1,21 @@ +// Check that LSan annotations work fine. +// RUN: %clangxx_hwasan -O0 %s -o %t && %run %t +// RUN: %clangxx_hwasan -O3 %s -o %t && %run %t + +#include +#include + +int *x, *y; + +int main() { + x = new int; + __lsan_ignore_object(x); + + { + __lsan::ScopedDisabler disabler; + y = new int; + } + + x = y = nullptr; + return 0; +} \ No newline at end of file diff --git a/compiler-rt/test/hwasan/TestCases/lsan_crash.cpp b/compiler-rt/test/hwasan/TestCases/lsan_crash.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/lsan_crash.cpp @@ -0,0 +1,31 @@ +// RUN: %clangxx_hwasan -O2 %s --std=c++14 -o %t && %run %t + +#include +#include +#include +#include +#include + +std::atomic done; + +void foo() { + std::unique_ptr mem; + + while (!done) + mem.reset(new char[1000000]); +} + +int main() { + std::vector threads; + for (int i = 0; i < 10; ++i) + threads.emplace_back(foo); + + for (int i = 0; i < 100; ++i) + __lsan_do_recoverable_leak_check(); + + done = true; + for (auto &t : threads) + t.join(); + + return 0; +}