[llvm-commits] [compiler-rt] r170869 - in /compiler-rt/trunk/lib/asan: asan_allocator.cc asan_allocator.h asan_allocator2.cc asan_flags.h asan_mac.cc asan_malloc_linux.cc asan_malloc_mac.cc asan_malloc_win.cc asan_new_delete.cc asan_report.cc asan_report.h asan_rtl.cc lit_tests/deep_stack_uaf.cc lit_tests/malloc_delete_mismatch.cc tests/asan_noinst_test.cc tests/asan_test.cc

Kostya Serebryany kcc at google.com
Fri Dec 21 00:54:00 PST 2012


Author: kcc
Date: Fri Dec 21 02:53:59 2012
New Revision: 170869

URL: http://llvm.org/viewvc/llvm-project?rev=170869&view=rev
Log:
[asan] add a flag alloc_dealloc_mismatch (off by default for now) which finds malloc/delete, new/free, new/delete[], etc mismatches

Added:
    compiler-rt/trunk/lib/asan/lit_tests/malloc_delete_mismatch.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_allocator.cc
    compiler-rt/trunk/lib/asan/asan_allocator.h
    compiler-rt/trunk/lib/asan/asan_allocator2.cc
    compiler-rt/trunk/lib/asan/asan_flags.h
    compiler-rt/trunk/lib/asan/asan_mac.cc
    compiler-rt/trunk/lib/asan/asan_malloc_linux.cc
    compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
    compiler-rt/trunk/lib/asan/asan_malloc_win.cc
    compiler-rt/trunk/lib/asan/asan_new_delete.cc
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/lib/asan/asan_report.h
    compiler-rt/trunk/lib/asan/asan_rtl.cc
    compiler-rt/trunk/lib/asan/lit_tests/deep_stack_uaf.cc
    compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc
    compiler-rt/trunk/lib/asan/tests/asan_test.cc

Modified: compiler-rt/trunk/lib/asan/asan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.cc Fri Dec 21 02:53:59 2012
@@ -128,7 +128,8 @@
 
   // Second 8 bytes.
   uptr alignment_log : 8;
-  uptr used_size : FIRST_32_SECOND_64(32, 56);  // Size requested by the user.
+  uptr alloc_type    : 2;
+  uptr used_size : FIRST_32_SECOND_64(32, 54);  // Size requested by the user.
 
   // This field may overlap with the user area and thus should not
   // be used while the chunk is in CHUNK_ALLOCATED state.
@@ -497,7 +498,8 @@
   return AsanChunkView(malloc_info.FindChunkByAddr(address));
 }
 
-static u8 *Allocate(uptr alignment, uptr size, StackTrace *stack) {
+static u8 *Allocate(uptr alignment, uptr size, StackTrace *stack,
+                    AllocType alloc_type) {
   __asan_init();
   CHECK(stack);
   if (size == 0) {
@@ -554,6 +556,7 @@
   CHECK(m);
   CHECK(m->chunk_state == CHUNK_AVAILABLE);
   m->chunk_state = CHUNK_ALLOCATED;
+  m->alloc_type = alloc_type;
   m->next = 0;
   CHECK(m->Size() == size_to_allocate);
   uptr addr = (uptr)m + REDZONE;
@@ -588,7 +591,7 @@
   return (u8*)addr;
 }
 
-static void Deallocate(u8 *ptr, StackTrace *stack) {
+static void Deallocate(u8 *ptr, StackTrace *stack, AllocType alloc_type) {
   if (!ptr) return;
   CHECK(stack);
 
@@ -609,6 +612,9 @@
     ReportFreeNotMalloced((uptr)ptr, stack);
   }
   CHECK(old_chunk_state == CHUNK_ALLOCATED);
+  if (m->alloc_type != alloc_type && flags()->alloc_dealloc_mismatch)
+    ReportAllocTypeMismatch((uptr)ptr, stack,
+                            (AllocType)m->alloc_type, (AllocType)alloc_type);
   // With REDZONE==16 m->next is in the user area, otherwise it should be 0.
   CHECK(REDZONE <= 16 || !m->next);
   CHECK(m->free_tid == kInvalidTid);
@@ -653,11 +659,11 @@
   CHECK(m->chunk_state == CHUNK_ALLOCATED);
   uptr old_size = m->used_size;
   uptr memcpy_size = Min(new_size, old_size);
-  u8 *new_ptr = Allocate(0, new_size, stack);
+  u8 *new_ptr = Allocate(0, new_size, stack, FROM_MALLOC);
   if (new_ptr) {
     CHECK(REAL(memcpy) != 0);
     REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
-    Deallocate(old_ptr, stack);
+    Deallocate(old_ptr, stack, FROM_MALLOC);
   }
   return new_ptr;
 }
@@ -682,27 +688,28 @@
 namespace __asan {
 
 SANITIZER_INTERFACE_ATTRIBUTE
-void *asan_memalign(uptr alignment, uptr size, StackTrace *stack) {
-  void *ptr = (void*)Allocate(alignment, size, stack);
+void *asan_memalign(uptr alignment, uptr size, StackTrace *stack,
+                    AllocType alloc_type) {
+  void *ptr = (void*)Allocate(alignment, size, stack, alloc_type);
   ASAN_MALLOC_HOOK(ptr, size);
   return ptr;
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
-void asan_free(void *ptr, StackTrace *stack) {
+void asan_free(void *ptr, StackTrace *stack, AllocType alloc_type) {
   ASAN_FREE_HOOK(ptr);
-  Deallocate((u8*)ptr, stack);
+  Deallocate((u8*)ptr, stack, alloc_type);
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
 void *asan_malloc(uptr size, StackTrace *stack) {
-  void *ptr = (void*)Allocate(0, size, stack);
+  void *ptr = (void*)Allocate(0, size, stack, FROM_MALLOC);
   ASAN_MALLOC_HOOK(ptr, size);
   return ptr;
 }
 
 void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
-  void *ptr = (void*)Allocate(0, nmemb * size, stack);
+  void *ptr = (void*)Allocate(0, nmemb * size, stack, FROM_MALLOC);
   if (ptr)
     REAL(memset)(ptr, 0, nmemb * size);
   ASAN_MALLOC_HOOK(ptr, size);
@@ -711,19 +718,19 @@
 
 void *asan_realloc(void *p, uptr size, StackTrace *stack) {
   if (p == 0) {
-    void *ptr = (void*)Allocate(0, size, stack);
+    void *ptr = (void*)Allocate(0, size, stack, FROM_MALLOC);
     ASAN_MALLOC_HOOK(ptr, size);
     return ptr;
   } else if (size == 0) {
     ASAN_FREE_HOOK(p);
-    Deallocate((u8*)p, stack);
+    Deallocate((u8*)p, stack, FROM_MALLOC);
     return 0;
   }
   return Reallocate((u8*)p, size, stack);
 }
 
 void *asan_valloc(uptr size, StackTrace *stack) {
-  void *ptr = (void*)Allocate(GetPageSizeCached(), size, stack);
+  void *ptr = (void*)Allocate(GetPageSizeCached(), size, stack, FROM_MALLOC);
   ASAN_MALLOC_HOOK(ptr, size);
   return ptr;
 }
@@ -735,14 +742,14 @@
     // pvalloc(0) should allocate one page.
     size = PageSize;
   }
-  void *ptr = (void*)Allocate(PageSize, size, stack);
+  void *ptr = (void*)Allocate(PageSize, size, stack, FROM_MALLOC);
   ASAN_MALLOC_HOOK(ptr, size);
   return ptr;
 }
 
 int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
                           StackTrace *stack) {
-  void *ptr = Allocate(alignment, size, stack);
+  void *ptr = Allocate(alignment, size, stack, FROM_MALLOC);
   CHECK(IsAligned((uptr)ptr, alignment));
   ASAN_MALLOC_HOOK(ptr, size);
   *memptr = ptr;

Modified: compiler-rt/trunk/lib/asan/asan_allocator.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.h?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.h (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.h Fri Dec 21 02:53:59 2012
@@ -27,6 +27,12 @@
 
 namespace __asan {
 
+enum AllocType {
+  FROM_MALLOC = 1,  // Memory block came from malloc, calloc, realloc, etc.
+  FROM_NEW = 2,     // Memory block came from operator new.
+  FROM_NEW_BR = 3   // Memory block came from operator new [ ]
+};
+
 static const uptr kNumberOfSizeClasses = 255;
 struct AsanChunk;
 
@@ -190,8 +196,9 @@
   FakeFrameLifo call_stack_;
 };
 
-void *asan_memalign(uptr alignment, uptr size, StackTrace *stack);
-void asan_free(void *ptr, StackTrace *stack);
+void *asan_memalign(uptr alignment, uptr size, StackTrace *stack,
+                    AllocType alloc_type);
+void asan_free(void *ptr, StackTrace *stack, AllocType alloc_type);
 
 void *asan_malloc(uptr size, StackTrace *stack);
 void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack);

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=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator2.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator2.cc Fri Dec 21 02:53:59 2012
@@ -124,8 +124,10 @@
   // 1-st 8 bytes.
   uptr chunk_state       : 8;  // Must be first.
   uptr alloc_tid         : 24;
+
   uptr free_tid          : 24;
   uptr from_memalign     : 1;
+  uptr alloc_type        : 2;
   // 2-nd 8 bytes
   uptr user_requested_size;
   // Header2 (intersects with user memory).
@@ -141,7 +143,9 @@
   // 1-st 8 bytes.
   uptr chunk_state       : 8;  // Must be first.
   uptr alloc_tid         : 24;
+
   uptr from_memalign     : 1;
+  uptr alloc_type        : 2;
   uptr free_tid          : 24;
   // 2-nd 8 bytes
   uptr user_requested_size;
@@ -271,7 +275,8 @@
   return res;
 }
 
-static void *Allocate(uptr size, uptr alignment, StackTrace *stack) {
+static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
+                      AllocType alloc_type) {
   Init();
   CHECK(stack);
   if (alignment < 8) alignment = 8;
@@ -306,6 +311,7 @@
   uptr chunk_beg = user_beg - kChunkHeaderSize;
   AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
   m->chunk_state = CHUNK_ALLOCATED;
+  m->alloc_type = alloc_type;
   u32 alloc_tid = t ? t->tid() : 0;
   m->alloc_tid = alloc_tid;
   CHECK_EQ(alloc_tid, m->alloc_tid);  // Does alloc_tid fit into the bitfield?
@@ -339,7 +345,7 @@
   return res;
 }
 
-static void Deallocate(void *ptr, StackTrace *stack) {
+static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
   uptr p = reinterpret_cast<uptr>(ptr);
   if (p == 0 || p == kReturnOnZeroMalloc) return;
   uptr chunk_beg = p - kChunkHeaderSize;
@@ -354,6 +360,9 @@
   else if (old_chunk_state != CHUNK_ALLOCATED)
     ReportFreeNotMalloced((uptr)ptr, stack);
   CHECK(old_chunk_state == CHUNK_ALLOCATED);
+  if (m->alloc_type != alloc_type && flags()->alloc_dealloc_mismatch)
+    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.
@@ -394,11 +403,11 @@
   CHECK(m->chunk_state == CHUNK_ALLOCATED);
   uptr old_size = m->UsedSize();
   uptr memcpy_size = Min(new_size, old_size);
-  void *new_ptr = Allocate(new_size, 8, stack);
+  void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC);
   if (new_ptr) {
     CHECK(REAL(memcpy) != 0);
     REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
-    Deallocate(old_ptr, stack);
+    Deallocate(old_ptr, stack, FROM_MALLOC);
   }
   return new_ptr;
 }
@@ -471,22 +480,23 @@
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
-void *asan_memalign(uptr alignment, uptr size, StackTrace *stack) {
-  return Allocate(size, alignment, stack);
+void *asan_memalign(uptr alignment, uptr size, StackTrace *stack,
+                    AllocType alloc_type) {
+  return Allocate(size, alignment, stack, alloc_type);
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
-void asan_free(void *ptr, StackTrace *stack) {
-  Deallocate(ptr, stack);
+void asan_free(void *ptr, StackTrace *stack, AllocType alloc_type) {
+  Deallocate(ptr, stack, alloc_type);
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
 void *asan_malloc(uptr size, StackTrace *stack) {
-  return Allocate(size, 8, stack);
+  return Allocate(size, 8, stack, FROM_MALLOC);
 }
 
 void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
-  void *ptr = Allocate(nmemb * size, 8, stack);
+  void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC);
   if (ptr)
     REAL(memset)(ptr, 0, nmemb * size);
   return ptr;
@@ -494,16 +504,16 @@
 
 void *asan_realloc(void *p, uptr size, StackTrace *stack) {
   if (p == 0)
-    return Allocate(size, 8, stack);
+    return Allocate(size, 8, stack, FROM_MALLOC);
   if (size == 0) {
-    Deallocate(p, stack);
+    Deallocate(p, stack, FROM_MALLOC);
     return 0;
   }
   return Reallocate(p, size, stack);
 }
 
 void *asan_valloc(uptr size, StackTrace *stack) {
-  return Allocate(size, GetPageSizeCached(), stack);
+  return Allocate(size, GetPageSizeCached(), stack, FROM_MALLOC);
 }
 
 void *asan_pvalloc(uptr size, StackTrace *stack) {
@@ -513,12 +523,12 @@
     // pvalloc(0) should allocate one page.
     size = PageSize;
   }
-  return Allocate(size, PageSize, stack);
+  return Allocate(size, PageSize, stack, FROM_MALLOC);
 }
 
 int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
                         StackTrace *stack) {
-  void *ptr = Allocate(size, alignment, stack);
+  void *ptr = Allocate(size, alignment, stack, FROM_MALLOC);
   CHECK(IsAligned((uptr)ptr, alignment));
   *memptr = ptr;
   return 0;

Modified: compiler-rt/trunk/lib/asan/asan_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.h?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_flags.h (original)
+++ compiler-rt/trunk/lib/asan/asan_flags.h Fri Dec 21 02:53:59 2012
@@ -102,6 +102,8 @@
   // Poison (or not) the heap memory on [de]allocation. Zero value is useful
   // for benchmarking the allocator or instrumentator.
   bool poison_heap;
+  // Report errors on malloc/delete, new/free, new/delete[], etc.
+  bool alloc_dealloc_mismatch;
 };
 
 Flags *flags();

Modified: compiler-rt/trunk/lib/asan/asan_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_mac.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_mac.cc Fri Dec 21 02:53:59 2012
@@ -319,7 +319,7 @@
   asan_register_worker_thread(context->parent_tid, &stack);
   // Call the original dispatcher for the block.
   context->func(context->block);
-  asan_free(context, &stack);
+  asan_free(context, &stack, FROM_MALLOC);
 }
 
 }  // namespace __asan
@@ -461,7 +461,7 @@
   worker_t fn = (worker_t)(ctxt->func);
   void *result =  fn(ctxt->block);
   GET_STACK_TRACE_THREAD;
-  asan_free(arg, &stack);
+  asan_free(arg, &stack, FROM_MALLOC);
   return result;
 }
 

Modified: compiler-rt/trunk/lib/asan/asan_malloc_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_linux.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_linux.cc Fri Dec 21 02:53:59 2012
@@ -61,12 +61,12 @@
 
 INTERCEPTOR(void, free, void *ptr) {
   GET_STACK_TRACE_FREE;
-  asan_free(ptr, &stack);
+  asan_free(ptr, &stack, FROM_MALLOC);
 }
 
 INTERCEPTOR(void, cfree, void *ptr) {
   GET_STACK_TRACE_FREE;
-  asan_free(ptr, &stack);
+  asan_free(ptr, &stack, FROM_MALLOC);
 }
 
 INTERCEPTOR(void*, malloc, uptr size) {
@@ -97,7 +97,7 @@
 
 INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
   GET_STACK_TRACE_MALLOC;
-  return asan_memalign(boundary, size, &stack);
+  return asan_memalign(boundary, size, &stack, FROM_MALLOC);
 }
 
 INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s)

Modified: compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_mac.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_mac.cc Fri Dec 21 02:53:59 2012
@@ -93,7 +93,7 @@
   } else {
     if (!asan_mz_size(ptr)) ptr = get_saved_cfallocator_ref(ptr);
     GET_STACK_TRACE_FREE;
-    asan_free(ptr, &stack);
+    asan_free(ptr, &stack, FROM_MALLOC);
   }
 }
 
@@ -165,7 +165,7 @@
     return malloc_zone_valloc(system_malloc_zone, size);
   }
   GET_STACK_TRACE_MALLOC;
-  return asan_memalign(GetPageSizeCached(), size, &stack);
+  return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC);
 }
 
 #define GET_ZONE_FOR_PTR(ptr) \
@@ -176,7 +176,7 @@
   if (!ptr) return;
   if (asan_mz_size(ptr)) {
     GET_STACK_TRACE_FREE;
-    asan_free(ptr, &stack);
+    asan_free(ptr, &stack, FROM_MALLOC);
   } else {
     // If the pointer does not belong to any of the zones, use one of the
     // fallback methods to free memory.
@@ -192,7 +192,7 @@
       ptr = get_saved_cfallocator_ref(ptr);
       GET_STACK_TRACE_FREE;
       if (!flags()->mac_ignore_invalid_free) {
-        asan_free(ptr, &stack);
+        asan_free(ptr, &stack, FROM_MALLOC);
       } else {
         GET_ZONE_FOR_PTR(ptr);
         WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack);
@@ -262,7 +262,7 @@
     return malloc_zone_memalign(system_malloc_zone, align, size);
   }
   GET_STACK_TRACE_MALLOC;
-  return asan_memalign(align, size, &stack);
+  return asan_memalign(align, size, &stack, FROM_MALLOC);
 }
 
 // This function is currently unused, and we build with -Werror.

Modified: compiler-rt/trunk/lib/asan/asan_malloc_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_win.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_win.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_win.cc Fri Dec 21 02:53:59 2012
@@ -32,7 +32,7 @@
 extern "C" {
 void free(void *ptr) {
   GET_STACK_TRACE_FREE;
-  return asan_free(ptr, &stack);
+  return asan_free(ptr, &stack, FROM_MALLOC);
 }
 
 void _free_dbg(void* ptr, int) {

Modified: compiler-rt/trunk/lib/asan/asan_new_delete.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_new_delete.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_new_delete.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_new_delete.cc Fri Dec 21 02:53:59 2012
@@ -35,32 +35,34 @@
 struct nothrow_t {};
 }  // namespace std
 
-#define OPERATOR_NEW_BODY \
+#define OPERATOR_NEW_BODY(type) \
   GET_STACK_TRACE_MALLOC;\
-  return asan_memalign(0, size, &stack);
+  return asan_memalign(0, size, &stack, type);
 
 INTERCEPTOR_ATTRIBUTE
-void *operator new(size_t size) { OPERATOR_NEW_BODY; }
+void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); }
 INTERCEPTOR_ATTRIBUTE
-void *operator new[](size_t size) { OPERATOR_NEW_BODY; }
+void *operator new[](size_t size) { OPERATOR_NEW_BODY(FROM_NEW_BR); }
 INTERCEPTOR_ATTRIBUTE
-void *operator new(size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
+void *operator new(size_t size, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY(FROM_NEW); }
 INTERCEPTOR_ATTRIBUTE
-void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
+void *operator new[](size_t size, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY(FROM_NEW_BR); }
 
-#define OPERATOR_DELETE_BODY \
+#define OPERATOR_DELETE_BODY(type) \
   GET_STACK_TRACE_FREE;\
-  asan_free(ptr, &stack);
+  asan_free(ptr, &stack, type);
 
 INTERCEPTOR_ATTRIBUTE
-void operator delete(void *ptr) { OPERATOR_DELETE_BODY; }
+void operator delete(void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW); }
 INTERCEPTOR_ATTRIBUTE
-void operator delete[](void *ptr) { OPERATOR_DELETE_BODY; }
+void operator delete[](void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW_BR); }
 INTERCEPTOR_ATTRIBUTE
 void operator delete(void *ptr, std::nothrow_t const&)
-{ OPERATOR_DELETE_BODY; }
+{ OPERATOR_DELETE_BODY(FROM_NEW); }
 INTERCEPTOR_ATTRIBUTE
 void operator delete[](void *ptr, std::nothrow_t const&)
-{ OPERATOR_DELETE_BODY; }
+{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }
 
 #endif

Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Fri Dec 21 02:53:59 2012
@@ -488,6 +488,26 @@
   DescribeHeapAddress(addr, 1);
 }
 
+void ReportAllocTypeMismatch(uptr addr, StackTrace *stack,
+                             AllocType alloc_type,
+                             AllocType dealloc_type) {
+  static const char *alloc_names[] =
+    {"INVALID", "malloc", "operator new", "operator new []"};
+  static const char *dealloc_names[] =
+    {"INVALID", "free", "operator delete", "operator delete []"};
+  CHECK_NE(alloc_type, dealloc_type);
+  ScopedInErrorReport in_report;
+  Decorator d;
+  Printf("%s", d.Warning());
+  Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
+        alloc_names[alloc_type], dealloc_names[dealloc_type], addr);
+  Printf("%s", d.EndWarning());
+  PrintStack(stack);
+  DescribeHeapAddress(addr, 1);
+  Report("HINT: if you don't care about these warnings you may set "
+         "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
+}
+
 void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
   ScopedInErrorReport in_report;
   Decorator d;

Modified: compiler-rt/trunk/lib/asan/asan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.h?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.h (original)
+++ compiler-rt/trunk/lib/asan/asan_report.h Fri Dec 21 02:53:59 2012
@@ -12,6 +12,7 @@
 // ASan-private header for error reporting functions.
 //===----------------------------------------------------------------------===//
 
+#include "asan_allocator.h"
 #include "asan_internal.h"
 #include "asan_thread.h"
 #include "sanitizer/asan_interface.h"
@@ -34,6 +35,9 @@
 void NORETURN ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr);
 void NORETURN ReportDoubleFree(uptr addr, StackTrace *stack);
 void NORETURN ReportFreeNotMalloced(uptr addr, StackTrace *stack);
+void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *stack,
+                                      AllocType alloc_type,
+                                      AllocType dealloc_type);
 void NORETURN ReportMallocUsableSizeNotOwned(uptr addr,
                                              StackTrace *stack);
 void NORETURN ReportAsanGetAllocatedSizeNotOwned(uptr addr,

Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Fri Dec 21 02:53:59 2012
@@ -107,6 +107,7 @@
   ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
   ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
   ParseFlag(str, &f->poison_heap, "poison_heap");
+  ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
 }
 
 void InitializeFlags(Flags *f, const char *env) {
@@ -143,6 +144,7 @@
   f->fast_unwind_on_fatal = true;
   f->fast_unwind_on_malloc = true;
   f->poison_heap = true;
+  f->alloc_dealloc_mismatch = false;
 
   // Override from user-specified string.
   ParseFlagsFromString(f, MaybeCallAsanDefaultOptions());

Modified: compiler-rt/trunk/lib/asan/lit_tests/deep_stack_uaf.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/deep_stack_uaf.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/deep_stack_uaf.cc (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/deep_stack_uaf.cc Fri Dec 21 02:53:59 2012
@@ -25,7 +25,7 @@
 };
 
 int main() {
-  char *x = new char[10];
+  char *x = (char*)malloc(10);
   // deep_free(x);
   DeepFree<200>::free(x);
   return x[5];

Added: compiler-rt/trunk/lib/asan/lit_tests/malloc_delete_mismatch.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/malloc_delete_mismatch.cc?rev=170869&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/malloc_delete_mismatch.cc (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/malloc_delete_mismatch.cc Fri Dec 21 02:53:59 2012
@@ -0,0 +1,26 @@
+// Check that we detect malloc/delete mismatch only if the approptiate flag
+// is set.
+
+// RUN: %clangxx_asan -g %s -o %t 2>&1
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1 %t 2>&1 | \
+// RUN: %symbolize | FileCheck %s
+
+// No error here.
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=0 %t
+#include <stdlib.h>
+
+static volatile char *x;
+
+int main() {
+  x = (char*)malloc(10);
+  x[0] = 0;
+  delete x;
+}
+// CHECK: ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete) on 0x
+// CHECK-NEXT: #0{{.*}}operator delete
+// CHECK-NEXT: #1{{.*}}main
+// CHECK: is located 0 bytes inside of 10-byte region
+// CHECK-NEXT: allocated by thread T0 here:
+// CHECK-NEXT: #0{{.*}}malloc
+// CHECK-NEXT: #1{{.*}}main
+// CHECK: HINT: if you don't care about these warnings you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0

Modified: compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc Fri Dec 21 02:53:59 2012
@@ -64,7 +64,7 @@
       void *ptr = vec[idx];
       vec[idx] = vec.back();
       vec.pop_back();
-      __asan::asan_free(ptr, &stack1);
+      __asan::asan_free(ptr, &stack1, __asan::FROM_MALLOC);
     } else {
       size_t size = my_rand(&seed) % 1000 + 1;
       switch ((my_rand(&seed) % 128)) {
@@ -73,7 +73,8 @@
         case 2: size += 4096; break;
       }
       size_t alignment = 1 << (my_rand(&seed) % 10 + 1);
-      char *ptr = (char*)__asan::asan_memalign(alignment, size, &stack2);
+      char *ptr = (char*)__asan::asan_memalign(alignment, size,
+                                               &stack2, __asan::FROM_MALLOC);
       vec.push_back(ptr);
       ptr[0] = 0;
       ptr[size-1] = 0;
@@ -81,7 +82,7 @@
     }
   }
   for (size_t i = 0; i < vec.size(); i++)
-    __asan::asan_free(vec[i], &stack3);
+    __asan::asan_free(vec[i], &stack3, __asan::FROM_MALLOC);
 }
 
 
@@ -262,12 +263,12 @@
 
   const int size = 32;
   void *p = __asan::asan_malloc(size, &stack);
-  __asan::asan_free(p, &stack);
+  __asan::asan_free(p, &stack, __asan::FROM_MALLOC);
   size_t i;
   size_t max_i = 1 << 30;
   for (i = 0; i < max_i; i++) {
     void *p1 = __asan::asan_malloc(size, &stack);
-    __asan::asan_free(p1, &stack);
+    __asan::asan_free(p1, &stack, __asan::FROM_MALLOC);
     if (p1 == p) break;
   }
   // fprintf(stderr, "i=%ld\n", i);
@@ -284,7 +285,7 @@
 
   for (size_t i = 0; i < 1000; i++) {
     void *p = __asan::asan_malloc(1 + (my_rand(&seed) % 4000), &stack);
-    __asan::asan_free(p, &stack);
+    __asan::asan_free(p, &stack, __asan::FROM_MALLOC);
   }
   return NULL;
 }
@@ -315,7 +316,7 @@
       p[i] = __asan::asan_malloc(32, &stack);
     }
     for (size_t i = 0; i < kNumMallocs; i++) {
-      __asan::asan_free(p[i], &stack);
+      __asan::asan_free(p[i], &stack, __asan::FROM_MALLOC);
     }
   }
   return NULL;

Modified: compiler-rt/trunk/lib/asan/tests/asan_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_test.cc?rev=170869&r1=170868&r2=170869&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Fri Dec 21 02:53:59 2012
@@ -1520,7 +1520,7 @@
   EXPECT_DEATH(Atoi(array + 9), RightOOBReadMessage(0));
   array[8] = '-';
   Atoi(array);
-  delete array;
+  free(array);
 }
 
 TEST(AddressSanitizer, AtoiAndFriendsOOBTest) {
@@ -1574,7 +1574,7 @@
   EXPECT_EQ(array, endptr);
   Strtol(array + 2, NULL, 0);
   EXPECT_EQ(array, endptr);
-  delete array;
+  free(array);
 }
 
 TEST(AddressSanitizer, StrtollOOBTest) {
@@ -1622,7 +1622,7 @@
                "AddressSanitizer: heap-buffer-overflow"
                ".* is located 4 bytes to the right of 10-byte region");
   close(fd);
-  delete x;
+  delete [] x;
 }
 
 TEST(AddressSanitizer, pread64) {
@@ -1634,7 +1634,7 @@
                "AddressSanitizer: heap-buffer-overflow"
                ".* is located 4 bytes to the right of 10-byte region");
   close(fd);
-  delete x;
+  delete [] x;
 }
 
 TEST(AddressSanitizer, read) {
@@ -1646,7 +1646,7 @@
                "AddressSanitizer: heap-buffer-overflow"
                ".* is located 4 bytes to the right of 10-byte region");
   close(fd);
-  delete x;
+  delete [] x;
 }
 
 #endif  // defined(__linux__) && !defined(ANDROID) && !defined(__ANDROID__)
@@ -1986,6 +1986,27 @@
   Ident(NoAddressSafety)();
 }
 
+static string MismatchStr(const string &str) {
+  return string("AddressSanitizer: alloc-dealloc-mismatch \\(") + str;
+}
+
+// This test is disabled until we enable alloc_dealloc_mismatch by default.
+// The feature is also tested by lit tests.
+TEST(AddressSanitizer, DISABLED_AllocDeallocMismatch) {
+  EXPECT_DEATH(free(Ident(new int)),
+               MismatchStr("operator new vs free"));
+  EXPECT_DEATH(free(Ident(new int[2])),
+               MismatchStr("operator new \\[\\] vs free"));
+  EXPECT_DEATH(delete (Ident(new int[2])),
+               MismatchStr("operator new \\[\\] vs operator delete"));
+  EXPECT_DEATH(delete (Ident((int*)malloc(2 * sizeof(int)))),
+               MismatchStr("malloc vs operator delete"));
+  EXPECT_DEATH(delete [] (Ident(new int)),
+               MismatchStr("operator new vs operator delete \\[\\]"));
+  EXPECT_DEATH(delete [] (Ident((int*)malloc(2 * sizeof(int)))),
+               MismatchStr("malloc vs operator delete \\[\\]"));
+}
+
 // ------------------ demo tests; run each one-by-one -------------
 // e.g. --gtest_filter=*DemoOOBLeftHigh --gtest_also_run_disabled_tests
 TEST(AddressSanitizer, DISABLED_DemoThreadedTest) {





More information about the llvm-commits mailing list