forked from OSchip/llvm-project
[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
This commit is contained in:
parent
3519dce968
commit
b1b8d1aa47
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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:
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue