summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/debugallocation.cc15
-rw-r--r--src/tests/debugallocation_test.cc18
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