From ad33ebead801f24d3197bc16f875501729e98485 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Wed, 16 Dec 2015 12:07:25 -0800 Subject: [PATCH] Fix bug in dlmalloc's version of calloc. 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 | 9 +++++++-- tests/malloc_test.cpp | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/libc/upstream-dlmalloc/malloc.c b/libc/upstream-dlmalloc/malloc.c index 3c9d36bf4..a61c0da9c 100644 --- a/libc/upstream-dlmalloc/malloc.c +++ b/libc/upstream-dlmalloc/malloc.c @@ -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; } diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp index b76625a7a..5af5a6fb5 100644 --- a/tests/malloc_test.cpp +++ b/tests/malloc_test.cpp @@ -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(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); + } +}