From 6d40d34908137c8d45e9bc303b4317b8303961ee Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Fri, 15 Aug 2014 18:42:58 -0700 Subject: [PATCH] Fix leak_realloc, copy entire allocation. Bug: 16874447 (cherry picked from commit 5df0839cea98bd8c37d8dba5b94b98e99c681a94) Change-Id: I9280505c0c1c3b5da24ba590448dcd6e7a230406 --- libc/bionic/malloc_debug_leak.cpp | 64 +++++++++++++++---------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp index 27b671432..df0f997e5 100644 --- a/libc/bionic/malloc_debug_leak.cpp +++ b/libc/bionic/malloc_debug_leak.cpp @@ -385,6 +385,36 @@ extern "C" void* leak_calloc(size_t n_elements, size_t elem_size) { return ptr; } +extern "C" size_t leak_malloc_usable_size(const void* mem) { + if (DebugCallsDisabled()) { + return g_malloc_dispatch->malloc_usable_size(mem); + } + + if (mem == NULL) { + return 0; + } + + // Check the guard to make sure it is valid. + const AllocationEntry* header = const_to_header(mem); + + if (header->guard == MEMALIGN_GUARD) { + // If this is a memalign'd pointer, then grab the header from + // entry. + header = const_to_header(header->entry); + } else if (header->guard != GUARD) { + debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n", + header->guard, header->entry); + return 0; + } + + size_t ret = g_malloc_dispatch->malloc_usable_size(header); + if (ret != 0) { + // The usable area starts at 'mem' and stops at 'header+ret'. + return reinterpret_cast(header) + ret - reinterpret_cast(mem); + } + return 0; +} + extern "C" void* leak_realloc(void* oldMem, size_t bytes) { if (DebugCallsDisabled()) { return g_malloc_dispatch->realloc(oldMem, bytes); @@ -408,7 +438,7 @@ extern "C" void* leak_realloc(void* oldMem, size_t bytes) { newMem = leak_malloc(bytes); if (newMem != NULL) { - size_t oldSize = header->entry->size & ~SIZE_FLAG_MASK; + size_t oldSize = leak_malloc_usable_size(oldMem); size_t copySize = (oldSize <= bytes) ? oldSize : bytes; memcpy(newMem, oldMem, copySize); leak_free(oldMem); @@ -462,38 +492,6 @@ extern "C" void* leak_memalign(size_t alignment, size_t bytes) { return base; } -extern "C" size_t leak_malloc_usable_size(const void* mem) { - if (DebugCallsDisabled()) { - return g_malloc_dispatch->malloc_usable_size(mem); - } - - if (mem != NULL) { - // Check the guard to make sure it is valid. - const AllocationEntry* header = const_to_header((void*)mem); - - if (header->guard == MEMALIGN_GUARD) { - // If this is a memalign'd pointer, then grab the header from - // entry. - header = const_to_header(header->entry); - } else if (header->guard != GUARD) { - debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n", - header->guard, header->entry); - return 0; - } - - // TODO: Temporary workaround to avoid a crash b/16874447. - return header->entry->size & ~SIZE_FLAG_MASK; -#if 0 - size_t ret = g_malloc_dispatch->malloc_usable_size(header); - if (ret != 0) { - // The usable area starts at 'mem' and stops at 'header+ret'. - return reinterpret_cast(header) + ret - reinterpret_cast(mem); - } -#endif - } - return 0; -} - extern "C" struct mallinfo leak_mallinfo() { return g_malloc_dispatch->mallinfo(); }