diff options
-rw-r--r-- | src/debugallocation.cc | 15 | ||||
-rw-r--r-- | src/tests/debugallocation_test.cc | 18 |
2 files changed, 31 insertions, 2 deletions
diff --git a/src/debugallocation.cc b/src/debugallocation.cc index 180b709..454818d 100644 --- a/src/debugallocation.cc +++ b/src/debugallocation.cc @@ -1226,8 +1226,19 @@ extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW { // return null if (p == NULL) return NULL; - memcpy(p->data_addr(), old->data_addr(), - (old->data_size() < size) ? old->data_size() : size); + // if ptr was allocated via memalign, then old->data_size() is not + // start of user data. So we must be careful to copy only user-data + char *old_begin = (char *)old->data_addr(); + char *old_end = old_begin + old->data_size(); + + ssize_t old_ssize = old_end - (char *)ptr; + // TODO: make FromRawPointer check for out-of-bounds offset values + CHECK_CONDITION(old_ssize >= 0); + + size_t old_size = (size_t)old_ssize; + CHECK_CONDITION(old_size <= old->data_size()); + + memcpy(p->data_addr(), ptr, (old_size < size) ? old_size : size); MallocHook::InvokeDeleteHook(ptr); MallocHook::InvokeNewHook(p->data_addr(), size); DebugDeallocate(ptr, MallocBlock::kMallocType); diff --git a/src/tests/debugallocation_test.cc b/src/tests/debugallocation_test.cc index f4a8567..beeb4cf 100644 --- a/src/tests/debugallocation_test.cc +++ b/src/tests/debugallocation_test.cc @@ -33,6 +33,8 @@ #include <stdio.h> #include <stdlib.h> +#include <malloc.h> // for memalign +#include <string.h> // for memcmp #include <vector> #include "gperftools/malloc_extension.h" #include "base/logging.h" @@ -296,6 +298,22 @@ TEST(DebugAllocationTest, HugeAlloc) { #endif } +// based on test program contributed by mikesart@gmail.com aka +// mikesart@valvesoftware.com. See issue-464. +TEST(DebugAllocationTest, ReallocAfterMemalloc) { + char stuff[50]; + memset(stuff, 0x11, sizeof(stuff)); + void *p = memalign(16, sizeof(stuff)); + EXPECT_NE(p, NULL); + memcpy(stuff, p, sizeof(stuff)); + + p = realloc(p, sizeof(stuff) + 10); + EXPECT_NE(p, NULL); + + int rv = memcmp(stuff, p, sizeof(stuff)); + EXPECT_EQ(rv, 0); +} + int main(int argc, char** argv) { // If you run without args, we run the non-death parts of the test. // Otherwise, argv[1] should be a number saying which death-test |