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