[asan] Prefer alloc-dealloc-mismatch to new-delete-type-mismatch.
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Wed, 13 Apr 2016 21:04:27 +0000 (21:04 +0000)
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Wed, 13 Apr 2016 21:04:27 +0000 (21:04 +0000)
With -fsized-deallocation, new[] vs delete mismatch is reported as
new-delete-type-mismatch. This is technically true, but
alloc-dealloc-mismatch describes it better.

llvm-svn: 266246

compiler-rt/lib/asan/asan_allocator.cc
compiler-rt/lib/asan/asan_report.cc
compiler-rt/lib/asan/asan_report.h
compiler-rt/test/asan/TestCases/Linux/new_delete_mismatch.cc [new file with mode: 0644]

index 6493c79..29a5ba6 100644 (file)
@@ -479,14 +479,6 @@ struct Allocator {
   void QuarantineChunk(AsanChunk *m, void *ptr, BufferedStackTrace *stack,
                        AllocType alloc_type) {
     CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
-
-    if (m->alloc_type != alloc_type) {
-      if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) {
-        ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type,
-                                (AllocType)alloc_type);
-      }
-    }
-
     CHECK_GE(m->alloc_tid, 0);
     if (SANITIZER_WORDSIZE == 64)  // On 32-bits this resides in user area.
       CHECK_EQ(m->free_tid, kInvalidTid);
@@ -523,14 +515,24 @@ struct Allocator {
 
     uptr chunk_beg = p - kChunkHeaderSize;
     AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
-    if (delete_size && flags()->new_delete_type_mismatch &&
-        delete_size != m->UsedSize()) {
-      ReportNewDeleteSizeMismatch(p, delete_size, stack);
-    }
+
     ASAN_FREE_HOOK(ptr);
     // Must mark the chunk as quarantined before any changes to its metadata.
     // Do not quarantine given chunk if we failed to set CHUNK_QUARANTINE flag.
     if (!AtomicallySetQuarantineFlagIfAllocated(m, ptr, stack)) return;
+
+    if (m->alloc_type != alloc_type) {
+      if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) {
+        ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type,
+                                (AllocType)alloc_type);
+      }
+    }
+
+    if (delete_size && flags()->new_delete_type_mismatch &&
+        delete_size != m->UsedSize()) {
+      ReportNewDeleteSizeMismatch(p, m->UsedSize(), delete_size, stack);
+    }
+
     QuarantineChunk(m, ptr, stack, alloc_type);
   }
 
index 9fb9d95..0d7d27a 100644 (file)
@@ -815,7 +815,7 @@ void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
   ReportErrorSummary("double-free", &stack);
 }
 
-void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
+void ReportNewDeleteSizeMismatch(uptr addr, uptr alloc_size, uptr delete_size,
                                  BufferedStackTrace *free_stack) {
   ScopedInErrorReport in_report;
   Decorator d;
@@ -829,7 +829,7 @@ void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
   Printf("%s  object passed to delete has wrong type:\n", d.EndWarning());
   Printf("  size of the allocated type:   %zd bytes;\n"
          "  size of the deallocated type: %zd bytes.\n",
-         asan_mz_size(reinterpret_cast<void*>(addr)), delete_size);
+         alloc_size, delete_size);
   CHECK_GT(free_stack->size, 0);
   ScarinessScore::PrintSimple(10, "new-delete-type-mismatch");
   GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
index 559b8ad..03f0965 100644 (file)
@@ -53,7 +53,7 @@ void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
                         uptr access_size, u32 exp, bool fatal);
 void ReportStackOverflow(const SignalContext &sig);
 void ReportDeadlySignal(const char *description, const SignalContext &sig);
-void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
+void ReportNewDeleteSizeMismatch(uptr addr, uptr alloc_size, uptr delete_size,
                                  BufferedStackTrace *free_stack);
 void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack);
 void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack);
diff --git a/compiler-rt/test/asan/TestCases/Linux/new_delete_mismatch.cc b/compiler-rt/test/asan/TestCases/Linux/new_delete_mismatch.cc
new file mode 100644 (file)
index 0000000..1cfc0ef
--- /dev/null
@@ -0,0 +1,16 @@
+// Check that we report new[] vs delete as alloc-dealloc-mismatch and not as
+// new-delete-type-mismatch when -fsized-deallocation is enabled.
+
+// RUN: %clangxx_asan -g %s -o %t && not %run %t |& FileCheck %s
+// RUN: %clangxx_asan -fsized-deallocation -g %s -o %t && not %run %t |& FileCheck %s
+
+#include <stdlib.h>
+
+static volatile char *x;
+
+int main() {
+  x = new char[10];
+  delete x;
+}
+
+// CHECK: AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs operator delete) on 0x