summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAliaksey Kandratsenka <alk@tut.by>2014-02-16 14:49:57 -0800
committerAliaksey Kandratsenka <alk@tut.by>2014-02-22 11:45:59 -0800
commita2375a1f360c0451ec2a2b852ea26a71fb731727 (patch)
treebfcf0c3c9a1633f477e872136eddce4823108cb8
parentd31f522f0e1b0e87ee3d5941e331ba745a0f5c23 (diff)
downloadgperftools-a2375a1f360c0451ec2a2b852ea26a71fb731727.tar.gz
issue-464: correctly handle realloc after memalign in debugalloc
debug memalign is creating special header block to allow us to find real allocated block. And previous implementation of data copying wasn't taking that into account and was copying that "alignment header" into newly allocated block.
-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