summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qmalloc.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-03-29 16:38:54 -0700
committerThiago Macieira <thiago.macieira@intel.com>2017-04-04 07:08:16 +0000
commit6a83f9aa98760d0ed1ab4c216a28a10862e86f00 (patch)
tree4ba7a7701b90f45fdac2a2cc7fb56e8f91f5d311 /src/corelib/global/qmalloc.cpp
parentc807dc3c122a2e21d6446231cd94f51cb0cf65d2 (diff)
Fix qReallocAligned for reallocation when alignment > 2*sizeof(void*)
When we call realloc, the alignment of the new block may be different from the old one. When that happens, we need to memmove the data to the new position, before we start overwriting things. Task-number: QTBUG-59804 Change-Id: I27b55fdf514247549455fffd14b07ea78918a3d0 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Diffstat (limited to 'src/corelib/global/qmalloc.cpp')
-rw-r--r--src/corelib/global/qmalloc.cpp11
1 files changed, 8 insertions, 3 deletions
diff --git a/src/corelib/global/qmalloc.cpp b/src/corelib/global/qmalloc.cpp
index f83cecd499..05676a0da2 100644
--- a/src/corelib/global/qmalloc.cpp
+++ b/src/corelib/global/qmalloc.cpp
@@ -40,6 +40,7 @@
#include "qplatformdefs.h"
#include <stdlib.h>
+#include <string.h>
/*
Define the container allocation functions in a separate file, so that our
@@ -79,8 +80,6 @@ void *qMallocAligned(size_t size, size_t alignment)
void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t alignment)
{
// fake an aligned allocation
- Q_UNUSED(oldsize);
-
void *actualptr = oldptr ? static_cast<void **>(oldptr)[-1] : 0;
if (alignment <= sizeof(void*)) {
// special, fast case
@@ -110,9 +109,15 @@ void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t align
quintptr faked = reinterpret_cast<quintptr>(real) + alignment;
faked &= ~(alignment - 1);
-
void **faked_ptr = reinterpret_cast<void **>(faked);
+ if (oldptr) {
+ qptrdiff oldoffset = static_cast<char *>(oldptr) - static_cast<char *>(actualptr);
+ qptrdiff newoffset = reinterpret_cast<char *>(faked_ptr) - static_cast<char *>(real);
+ if (oldoffset != newoffset)
+ memmove(faked_ptr, static_cast<char *>(real) + oldoffset, qMin(oldsize, newsize));
+ }
+
// now save the value of the real pointer at faked-sizeof(void*)
// by construction, alignment > sizeof(void*) and is a power of 2, so
// faked-sizeof(void*) is properly aligned for a pointer