[compiler-rt] r173776 - [ASan] Do allocate memory even for zero-size allocation requests. Explain why we have to do this in comments.

Alexey Samsonov samsonov at google.com
Mon Jan 28 23:51:35 PST 2013


Author: samsonov
Date: Tue Jan 29 01:51:34 2013
New Revision: 173776

URL: http://llvm.org/viewvc/llvm-project?rev=173776&view=rev
Log:
[ASan] Do allocate memory even for zero-size allocation requests. Explain why we have to do this in comments.

Modified:
    compiler-rt/trunk/lib/asan/asan_allocator2.cc
    compiler-rt/trunk/lib/asan/tests/asan_test.cc

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=173776&r1=173775&r2=173776&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator2.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator2.cc Tue Jan 29 01:51:34 2013
@@ -95,8 +95,6 @@ static const uptr kMaxAllowedMallocSize 
 static const uptr kMaxThreadLocalQuarantine =
   FIRST_32_SECOND_64(1 << 18, 1 << 20);
 
-static const uptr kReturnOnZeroMalloc = 2048;  // Zero page is protected.
-
 // Every chunk of memory allocated by this allocator can be in one of 3 states:
 // CHUNK_AVAILABLE: the chunk is in the free list and ready to be allocated.
 // CHUNK_ALLOCATED: the chunk is allocated and not yet freed.
@@ -309,10 +307,12 @@ static void *Allocate(uptr size, uptr al
   if (alignment < min_alignment)
     alignment = min_alignment;
   if (size == 0) {
-    if (alignment <= kReturnOnZeroMalloc)
-      return reinterpret_cast<void *>(kReturnOnZeroMalloc);
-    else
-      return 0;  // 0 bytes with large alignment requested. Just return 0.
+    // We'd be happy to avoid allocating memory for zero-size requests, but
+    // some programs/tests depend on this behavior and assume that malloc would
+    // not return NULL even for zero-size allocations. Moreover, it looks like
+    // operator new should never return NULL, and results of consecutive "new"
+    // calls must be different even if the allocated size is zero.
+    size = 1;
   }
   CHECK(IsPowerOfTwo(alignment));
   uptr rz_log = ComputeRZLog(size);
@@ -418,7 +418,7 @@ static void *Allocate(uptr size, uptr al
 
 static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
   uptr p = reinterpret_cast<uptr>(ptr);
-  if (p == 0 || p == kReturnOnZeroMalloc) return;
+  if (p == 0) return;
   uptr chunk_beg = p - kChunkHeaderSize;
   AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
 
@@ -612,7 +612,7 @@ void *asan_calloc(uptr nmemb, uptr size,
 }
 
 void *asan_realloc(void *p, uptr size, StackTrace *stack) {
-  if (p == 0 || reinterpret_cast<uptr>(p) == kReturnOnZeroMalloc)
+  if (p == 0)
     return Allocate(size, 8, stack, FROM_MALLOC);
   if (size == 0) {
     Deallocate(p, stack, FROM_MALLOC);
@@ -678,7 +678,7 @@ uptr __asan_get_estimated_allocated_size
 
 bool __asan_get_ownership(const void *p) {
   uptr ptr = reinterpret_cast<uptr>(p);
-  return (ptr == kReturnOnZeroMalloc) || (AllocationSize(ptr) > 0);
+  return (AllocationSize(ptr) > 0);
 }
 
 uptr __asan_get_allocated_size(const void *p) {
@@ -686,7 +686,7 @@ uptr __asan_get_allocated_size(const voi
   uptr ptr = reinterpret_cast<uptr>(p);
   uptr allocated_size = AllocationSize(ptr);
   // Die if p is not malloced or if it is already freed.
-  if (allocated_size == 0 && ptr != kReturnOnZeroMalloc) {
+  if (allocated_size == 0) {
     GET_STACK_TRACE_FATAL_HERE;
     ReportAsanGetAllocatedSizeNotOwned(ptr, &stack);
   }

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=173776&r1=173775&r2=173776&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Tue Jan 29 01:51:34 2013
@@ -391,6 +391,26 @@ TEST(AddressSanitizer, ReallocTest) {
   free(ptr2);
 }
 
+TEST(AddressSanitizer, ZeroSizeMallocTest) {
+  // Test that malloc(0) and similar functions don't return NULL.
+  void *ptr = Ident(malloc(0));
+  EXPECT_FALSE(0 == ptr);
+  free(ptr);
+#if !defined(__APPLE__) && !defined(ANDROID) && !defined(__ANDROID__)
+  int pm_res = posix_memalign(&ptr, 1<<20, 0);
+  EXPECT_EQ(0, pm_res);
+  EXPECT_FALSE(0 == ptr);
+  free(ptr);
+#endif
+  int *int_ptr = new int [0];
+  int *int_ptr2 = new int[0];
+  EXPECT_FALSE(0 == int_ptr);
+  EXPECT_FALSE(0 == int_ptr2);
+  EXPECT_FALSE(int_ptr == int_ptr2);
+  delete[] int_ptr;
+  delete[] int_ptr2;
+}
+
 #ifndef __APPLE__
 static const char *kMallocUsableSizeErrorMsg =
   "AddressSanitizer: attempting to call malloc_usable_size()";





More information about the llvm-commits mailing list