OSDN Git Service

Fix bug in dlmalloc's version of calloc.
authorChristopher Ferris <cferris@google.com>
Wed, 16 Dec 2015 20:07:25 +0000 (12:07 -0800)
committerChristopher Ferris <cferris@google.com>
Wed, 16 Dec 2015 22:48:03 +0000 (14:48 -0800)
Under some circumstances, doing a calloc will make sure that the memory
returned will be zero up to the size of the requested size. However, if
there is more usable size than the requested size, that extra part
of the allocation will not be zeroed. This change fixes it so that the
entire usable memory is always zeroed.

Change-Id: I8a66d6767c074023c4ba3568bf2705e1886740fc

libc/upstream-dlmalloc/malloc.c
tests/malloc_test.cpp

index 3c9d36b..a61c0da 100644 (file)
@@ -4822,8 +4822,13 @@ void* dlcalloc(size_t n_elements, size_t elem_size) {
       req = MAX_SIZE_T; /* force downstream failure on overflow */
   }
   mem = dlmalloc(req);
-  if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
-    memset(mem, 0, req);
+  if (mem != 0) {
+    mchunkptr p = mem2chunk(mem);
+    if (calloc_must_clear(p)) {
+      /* Make sure to clear all of the buffer, not just the requested size. */
+      memset(mem, 0, chunksize(p) - overhead_for(p));
+    }
+  }
   return mem;
 }
 
index b76625a..5af5a6f 100644 (file)
@@ -372,3 +372,22 @@ TEST(malloc, malloc_info) {
   }
 #endif
 }
+
+TEST(malloc, calloc_usable_size) {
+  for (size_t size = 1; size <= 2048; size++) {
+    void* pointer = malloc(size);
+    ASSERT_TRUE(pointer != nullptr);
+    memset(pointer, 0xeb, malloc_usable_size(pointer));
+    free(pointer);
+
+    // We should get a previous pointer that has been set to non-zero.
+    // If calloc does not zero out all of the data, this will fail.
+    uint8_t* zero_mem = reinterpret_cast<uint8_t*>(calloc(1, size));
+    ASSERT_TRUE(pointer != nullptr);
+    size_t usable_size = malloc_usable_size(zero_mem);
+    for (size_t i = 0; i < usable_size; i++) {
+      ASSERT_EQ(0, zero_mem[i]) << "Failed at allocation size " << size << " at byte " << i;
+    }
+    free(zero_mem);
+  }
+}