[PATCH] [lsan] Make LSan ignore memory poisoned by ASan.

Sergey Matveev earthdok at google.com
Sat Dec 7 12:56:00 PST 2013


Hi kcc,

No more (potenital) false negatives due to red zones or fake stack
frames.

http://llvm-reviews.chandlerc.com/D2359

Files:
  lib/asan/asan_poisoning.cc
  lib/lsan/lit_tests/AsanConfig/lit.cfg
  lib/lsan/lit_tests/LsanConfig/lit.cfg
  lib/lsan/lit_tests/TestCases/AsanOnly/use_poisoned.cc
  lib/lsan/lsan.cc
  lib/lsan/lsan_common.cc
  lib/lsan/lsan_common.h

Index: lib/asan/asan_poisoning.cc
===================================================================
--- lib/asan/asan_poisoning.cc
+++ lib/asan/asan_poisoning.cc
@@ -292,3 +292,11 @@
     *(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(void *));  // NOLINT
+}
+}
+
Index: lib/lsan/lit_tests/AsanConfig/lit.cfg
===================================================================
--- lib/lsan/lit_tests/AsanConfig/lit.cfg
+++ lib/lsan/lit_tests/AsanConfig/lit.cfg
@@ -17,6 +17,8 @@
   lit_config.fatal("Can't find common LSan lit config at: %r" % lsan_lit_cfg)
 lit_config.load_config(config, lsan_lit_cfg)
 
+config.tool = 'asan'
+
 config.name = 'LeakSanitizer-AddressSanitizer'
 
 clang_lsan_cxxflags = config.clang_cxxflags + " -fsanitize=address "
Index: lib/lsan/lit_tests/LsanConfig/lit.cfg
===================================================================
--- lib/lsan/lit_tests/LsanConfig/lit.cfg
+++ lib/lsan/lit_tests/LsanConfig/lit.cfg
@@ -17,6 +17,8 @@
   lit_config.fatal("Can't find common LSan lit config at: %r" % lsan_lit_cfg)
 lit_config.load_config(config, lsan_lit_cfg)
 
+config.tool = 'standalone'
+
 config.name = 'LeakSanitizer-Standalone'
 
 clang_lsan_cxxflags = config.clang_cxxflags + " -fsanitize=leak "
Index: lib/lsan/lit_tests/TestCases/AsanOnly/use_poisoned.cc
===================================================================
--- /dev/null
+++ lib/lsan/lit_tests/TestCases/AsanOnly/use_poisoned.cc
@@ -0,0 +1,24 @@
+// Test for the use_poisoned flag.
+// 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:
Index: lib/lsan/lsan.cc
===================================================================
--- lib/lsan/lsan.cc
+++ lib/lsan/lsan.cc
@@ -35,6 +35,11 @@
   ParseCommonFlagsFromString(cf, GetEnv("LSAN_OPTIONS"));
 }
 
+///// Interface to the common LSan module. /////
+bool WordIsPoisoned(uptr addr) {
+  return false;
+}
+
 }  // namespace __lsan
 
 using namespace __lsan;  // NOLINT
Index: lib/lsan/lsan_common.cc
===================================================================
--- lib/lsan/lsan_common.cc
+++ lib/lsan/lsan_common.cc
@@ -47,6 +47,7 @@
   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 @@
     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 @@
     // 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,
Index: lib/lsan/lsan_common.h
===================================================================
--- lib/lsan/lsan_common.h
+++ lib/lsan/lsan_common.h
@@ -66,6 +66,8 @@
 
   // 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 @@
 // 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();
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2359.1.patch
Type: text/x-patch
Size: 4876 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131207/afd28d11/attachment.bin>


More information about the llvm-commits mailing list