diff options
author | Sergey Matveev <earthdok@google.com> | 2013-12-09 13:12:10 +0000 |
---|---|---|
committer | Sergey Matveev <earthdok@google.com> | 2013-12-09 13:12:10 +0000 |
commit | b1b8d1aa4785666f319782a63f44a34df2c7232c (patch) | |
tree | 389c1f5f28c85f4a3b1aa09b5a84073f886a87c6 | |
parent | 3519dce968d307ee9fedca7c25ff6624549fd185 (diff) | |
download | bcm5719-llvm-b1b8d1aa4785666f319782a63f44a34df2c7232c.tar.gz bcm5719-llvm-b1b8d1aa4785666f319782a63f44a34df2c7232c.zip |
[lsan] Make LSan ignore memory poisoned by ASan.
Summary:
No more (potenital) false negatives due to red zones or fake stack
frames.
Reviewers: kcc, samsonov
Reviewed By: samsonov
CC: llvm-commits, samsonov
Differential Revision: http://llvm-reviews.chandlerc.com/D2359
llvm-svn: 196778
-rw-r--r-- | compiler-rt/lib/asan/asan_poisoning.cc | 8 | ||||
-rw-r--r-- | compiler-rt/lib/lsan/lit_tests/AsanConfig/lit.cfg | 2 | ||||
-rw-r--r-- | compiler-rt/lib/lsan/lit_tests/TestCases/use_poisoned_asan.cc | 25 | ||||
-rw-r--r-- | compiler-rt/lib/lsan/lsan.cc | 5 | ||||
-rw-r--r-- | compiler-rt/lib/lsan/lsan_common.cc | 13 | ||||
-rw-r--r-- | compiler-rt/lib/lsan/lsan_common.h | 4 |
6 files changed, 57 insertions, 0 deletions
diff --git a/compiler-rt/lib/asan/asan_poisoning.cc b/compiler-rt/lib/asan/asan_poisoning.cc index ef3ba9fb659..cc42b31a27e 100644 --- a/compiler-rt/lib/asan/asan_poisoning.cc +++ b/compiler-rt/lib/asan/asan_poisoning.cc @@ -292,3 +292,11 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p, *(u8*)MemToShadow(b1) = static_cast<u8>(new_mid - b1); } } + +// --- Implementation of LSan-specific functions --- {{{1 +namespace __lsan { +bool WordIsPoisoned(uptr addr) { + return __asan_region_is_poisoned(addr, sizeof(uptr)); +} +} + diff --git a/compiler-rt/lib/lsan/lit_tests/AsanConfig/lit.cfg b/compiler-rt/lib/lsan/lit_tests/AsanConfig/lit.cfg index ae9198173ff..edb5adfd3b6 100644 --- a/compiler-rt/lib/lsan/lit_tests/AsanConfig/lit.cfg +++ b/compiler-rt/lib/lsan/lit_tests/AsanConfig/lit.cfg @@ -17,6 +17,8 @@ if not os.path.exists(lsan_lit_cfg): lit_config.fatal("Can't find common LSan lit config at: %r" % lsan_lit_cfg) lit_config.load_config(config, lsan_lit_cfg) +config.available_features.add('asan') + config.name = 'LeakSanitizer-AddressSanitizer' clang_lsan_cxxflags = config.clang_cxxflags + " -fsanitize=address " diff --git a/compiler-rt/lib/lsan/lit_tests/TestCases/use_poisoned_asan.cc b/compiler-rt/lib/lsan/lit_tests/TestCases/use_poisoned_asan.cc new file mode 100644 index 00000000000..77a4af20b83 --- /dev/null +++ b/compiler-rt/lib/lsan/lit_tests/TestCases/use_poisoned_asan.cc @@ -0,0 +1,25 @@ +// ASan-poisoned memory should be ignored if use_poisoned is false. +// REQUIRES: asan +// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" +// RUN: %clangxx_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_poisoned=0" not %t 2>&1 | FileCheck %s +// RUN: LSAN_OPTIONS=$LSAN_BASE:"use_poisoned=1" %t 2>&1 + +#include <stdio.h> +#include <stdlib.h> +#include <sanitizer/asan_interface.h> +#include <assert.h> + +void **p; + +int main() { + p = new void *; + *p = malloc(1337); + fprintf(stderr, "Test alloc: %p.\n", *p); + __asan_poison_memory_region(p, sizeof(*p)); + return 0; +} +// CHECK: Test alloc: [[ADDR:.*]]. +// CHECK: Directly leaked 1337 byte object at [[ADDR]] +// CHECK: LeakSanitizer: detected memory leaks +// CHECK: SUMMARY: AddressSanitizer: diff --git a/compiler-rt/lib/lsan/lsan.cc b/compiler-rt/lib/lsan/lsan.cc index 43cfcda42ca..203590eb77c 100644 --- a/compiler-rt/lib/lsan/lsan.cc +++ b/compiler-rt/lib/lsan/lsan.cc @@ -35,6 +35,11 @@ static void InitializeCommonFlags() { ParseCommonFlagsFromString(cf, GetEnv("LSAN_OPTIONS")); } +///// Interface to the common LSan module. ///// +bool WordIsPoisoned(uptr addr) { + return false; +} + } // namespace __lsan using namespace __lsan; // NOLINT diff --git a/compiler-rt/lib/lsan/lsan_common.cc b/compiler-rt/lib/lsan/lsan_common.cc index 152588411e2..8ad96f23e23 100644 --- a/compiler-rt/lib/lsan/lsan_common.cc +++ b/compiler-rt/lib/lsan/lsan_common.cc @@ -47,6 +47,7 @@ static void InitializeFlags() { f->use_stacks = true; f->use_tls = true; f->use_unaligned = false; + f->use_poisoned = false; f->verbosity = 0; f->log_pointers = false; f->log_threads = false; @@ -58,6 +59,7 @@ static void InitializeFlags() { ParseFlag(options, &f->use_stacks, "use_stacks"); ParseFlag(options, &f->use_tls, "use_tls"); ParseFlag(options, &f->use_unaligned, "use_unaligned"); + ParseFlag(options, &f->use_poisoned, "use_poisoned"); ParseFlag(options, &f->report_objects, "report_objects"); ParseFlag(options, &f->resolution, "resolution"); CHECK_GE(&f->resolution, 0); @@ -148,6 +150,17 @@ void ScanRangeForPointers(uptr begin, uptr end, // Reachable beats ignored beats leaked. if (m.tag() == kReachable) continue; if (m.tag() == kIgnored && tag != kReachable) continue; + + // Do this check relatively late so we can log only the interesting cases. + if (!flags()->use_poisoned && WordIsPoisoned(pp)) { + if (flags()->log_pointers) + Report( + "%p is poisoned: ignoring %p pointing into chunk %p-%p of size " + "%zu.\n", + pp, p, chunk, chunk + m.requested_size(), m.requested_size()); + continue; + } + m.set_tag(tag); if (flags()->log_pointers) Report("%p: found %p pointing into chunk %p-%p of size %zu.\n", pp, p, diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index d490f8bafd9..714f8b65010 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -66,6 +66,8 @@ struct Flags { // Consider unaligned pointers valid. bool use_unaligned; + // Consider pointers found in poisoned memory to be valid. + bool use_poisoned; // User-visible verbosity. int verbosity; @@ -129,6 +131,8 @@ void GetAllocatorGlobalRange(uptr *begin, uptr *end); // Wrappers for allocator's ForceLock()/ForceUnlock(). void LockAllocator(); void UnlockAllocator(); +// Returns true if [addr, addr + sizeof(void *)) is poisoned. +bool WordIsPoisoned(uptr addr); // Wrappers for ThreadRegistry access. void LockThreadRegistry(); void UnlockThreadRegistry(); |