diff options
author | Maxim Ostapenko <chefmax7@gmail.com> | 2017-09-22 07:11:43 +0000 |
---|---|---|
committer | Maxim Ostapenko <chefmax7@gmail.com> | 2017-09-22 07:11:43 +0000 |
commit | acea4097cecbb48fab482ada95e585f54a5e7436 (patch) | |
tree | 26d87f9723bc6a1cbc366cc72997fb16500b09e7 | |
parent | 0b01c05ec7545697a453b594f3b288e38d4c36cb (diff) |
[asan/lsan] Make LSan compliant with recovery mode when running on top of ASan
Don't overwrite exit code in LSan when running on top of ASan in recovery mode
to avoid breakage of users code due to found leaks.
Patch by Slava Barinov.
Differential Revision: https://reviews.llvm.org/D38026
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@313966 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/asan/asan_rtl.cc | 5 | ||||
-rw-r--r-- | lib/lsan/lsan_common.cc | 3 | ||||
-rw-r--r-- | lib/lsan/lsan_common.h | 1 | ||||
-rw-r--r-- | test/asan/TestCases/recoverable-lsan.cc | 21 |
4 files changed, 29 insertions, 1 deletions
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc index 6e83671ab..8608e4a60 100644 --- a/lib/asan/asan_rtl.cc +++ b/lib/asan/asan_rtl.cc @@ -459,7 +459,10 @@ static void AsanInitInternal() { if (CAN_SANITIZE_LEAKS) { __lsan::InitCommonLsan(); if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { - Atexit(__lsan::DoLeakCheck); + if (flags()->halt_on_error) + Atexit(__lsan::DoLeakCheck); + else + Atexit(__lsan::DoRecoverableLeakCheckVoid); } } diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc index a7927684c..b9b6fe086 100644 --- a/lib/lsan/lsan_common.cc +++ b/lib/lsan/lsan_common.cc @@ -593,6 +593,8 @@ static int DoRecoverableLeakCheck() { return have_leaks ? 1 : 0; } +void DoRecoverableLeakCheckVoid() { DoRecoverableLeakCheck(); } + static Suppression *GetSuppressionForAddr(uptr addr) { Suppression *s = nullptr; @@ -755,6 +757,7 @@ uptr LeakReport::UnsuppressedLeakCount() { namespace __lsan { void InitCommonLsan() { } void DoLeakCheck() { } +void DoRecoverableLeakCheckVoid() { } void DisableInThisThread() { } void EnableInThisThread() { } } diff --git a/lib/lsan/lsan_common.h b/lib/lsan/lsan_common.h index 31bf3eb1d..1bb3e4198 100644 --- a/lib/lsan/lsan_common.h +++ b/lib/lsan/lsan_common.h @@ -145,6 +145,7 @@ enum IgnoreObjectResult { // Functions called from the parent tool. void InitCommonLsan(); void DoLeakCheck(); +void DoRecoverableLeakCheckVoid(); void DisableCounterUnderflow(); bool DisabledInThisThread(); diff --git a/test/asan/TestCases/recoverable-lsan.cc b/test/asan/TestCases/recoverable-lsan.cc new file mode 100644 index 000000000..997206012 --- /dev/null +++ b/test/asan/TestCases/recoverable-lsan.cc @@ -0,0 +1,21 @@ +// Ensure that output is the same but exit code depends on halt_on_error value +// RUN: %clangxx_asan %s -o %t +// RUN: %env_asan_opts="halt_on_error=0" %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts="halt_on_error=1" not %run %t 2>&1 | FileCheck %s +// RUN: not %run %t 2>&1 | FileCheck %s + +#include <stdlib.h> + +int f() { + volatile int *a = (int *)malloc(20); + a[0] = 1; + return a[0]; +} + +int main() { + f(); + f(); +} + +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: SUMMARY: AddressSanitizer: 20 byte(s) leaked |