summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergey Matveev <earthdok@google.com>2013-12-09 13:12:10 +0000
committerSergey Matveev <earthdok@google.com>2013-12-09 13:12:10 +0000
commitb1b8d1aa4785666f319782a63f44a34df2c7232c (patch)
tree389c1f5f28c85f4a3b1aa09b5a84073f886a87c6
parent3519dce968d307ee9fedca7c25ff6624549fd185 (diff)
downloadbcm5719-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.cc8
-rw-r--r--compiler-rt/lib/lsan/lit_tests/AsanConfig/lit.cfg2
-rw-r--r--compiler-rt/lib/lsan/lit_tests/TestCases/use_poisoned_asan.cc25
-rw-r--r--compiler-rt/lib/lsan/lsan.cc5
-rw-r--r--compiler-rt/lib/lsan/lsan_common.cc13
-rw-r--r--compiler-rt/lib/lsan/lsan_common.h4
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();
OpenPOWER on IntegriCloud