[compiler-rt] r198932 - [lsan] handle 'new T[0]' where T is a type with DTOR; fixes https://code.google.com/p/address-sanitizer/issues/detail?id=257

Kostya Serebryany kcc at google.com
Fri Jan 10 02:48:01 PST 2014


Author: kcc
Date: Fri Jan 10 04:48:01 2014
New Revision: 198932

URL: http://llvm.org/viewvc/llvm-project?rev=198932&view=rev
Log:
[lsan] handle 'new T[0]' where T is a type with DTOR; fixes https://code.google.com/p/address-sanitizer/issues/detail?id=257

Added:
    compiler-rt/trunk/lib/lsan/lit_tests/TestCases/new_array_with_dtor_0.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_allocator2.cc
    compiler-rt/trunk/lib/lsan/lsan_allocator.cc
    compiler-rt/trunk/lib/lsan/lsan_common.h

Modified: compiler-rt/trunk/lib/asan/asan_allocator2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator2.cc?rev=198932&r1=198931&r2=198932&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator2.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator2.cc Fri Jan 10 04:48:01 2014
@@ -710,8 +710,12 @@ uptr PointsIntoChunk(void* p) {
   __asan::AsanChunk *m = __asan::GetAsanChunkByAddrFastLocked(addr);
   if (!m) return 0;
   uptr chunk = m->Beg();
-  if ((m->chunk_state == __asan::CHUNK_ALLOCATED) &&
-      m->AddrIsInside(addr, /*locked_version=*/true))
+  if (m->chunk_state != __asan::CHUNK_ALLOCATED)
+    return 0;
+  if (m->AddrIsInside(addr, /*locked_version=*/true))
+    return chunk;
+  if (IsSpecialCaseOfOperatorNew0(chunk, m->UsedSize(/*locked_version*/ true),
+                                  addr))
     return chunk;
   return 0;
 }

Added: compiler-rt/trunk/lib/lsan/lit_tests/TestCases/new_array_with_dtor_0.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lit_tests/TestCases/new_array_with_dtor_0.cc?rev=198932&view=auto
==============================================================================
--- compiler-rt/trunk/lib/lsan/lit_tests/TestCases/new_array_with_dtor_0.cc (added)
+++ compiler-rt/trunk/lib/lsan/lit_tests/TestCases/new_array_with_dtor_0.cc Fri Jan 10 04:48:01 2014
@@ -0,0 +1,19 @@
+// Regression test:
+// https://code.google.com/p/address-sanitizer/issues/detail?id=257
+// RUN: %clangxx_lsan %s -o %t && %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+
+struct T {
+  ~T() { printf("~T\n"); }
+};
+
+T *t;
+
+int main(int argc, char **argv) {
+  t = new T[argc - 1];
+  printf("OK\n");
+}
+
+// CHECK: OK
+

Modified: compiler-rt/trunk/lib/lsan/lsan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_allocator.cc?rev=198932&r1=198931&r2=198932&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_allocator.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan_allocator.cc Fri Jan 10 04:48:01 2014
@@ -143,7 +143,11 @@ uptr PointsIntoChunk(void* p) {
   if (addr < chunk) return 0;
   ChunkMetadata *m = Metadata(reinterpret_cast<void *>(chunk));
   CHECK(m);
-  if (m->allocated && addr < chunk + m->requested_size)
+  if (!m->allocated)
+    return 0;
+  if (addr < chunk + m->requested_size)
+    return chunk;
+  if (IsSpecialCaseOfOperatorNew0(chunk, m->requested_size, addr))
     return chunk;
   return 0;
 }

Modified: compiler-rt/trunk/lib/lsan/lsan_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.h?rev=198932&r1=198931&r2=198932&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_common.h (original)
+++ compiler-rt/trunk/lib/lsan/lsan_common.h Fri Jan 10 04:48:01 2014
@@ -139,6 +139,15 @@ void InitCommonLsan();
 void DoLeakCheck();
 bool DisabledInThisThread();
 
+// Special case for "new T[0]" where T is a type with DTOR.
+// new T[0] will allocate one word for the array size (0) and store a pointer
+// to the end of allocated chunk.
+inline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size,
+                                        uptr addr) {
+  return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr &&
+         *reinterpret_cast<uptr *>(chunk_beg) == 0;
+}
+
 // The following must be implemented in the parent tool.
 
 void ForEachChunk(ForEachChunkCallback callback, void *arg);





More information about the llvm-commits mailing list