From 6a83f9aa98760d0ed1ab4c216a28a10862e86f00 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 29 Mar 2017 16:38:54 -0700 Subject: 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 --- src/corelib/global/qmalloc.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/corelib/global/qmalloc.cpp') 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 +#include /* 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(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(real) + alignment; faked &= ~(alignment - 1); - void **faked_ptr = reinterpret_cast(faked); + if (oldptr) { + qptrdiff oldoffset = static_cast(oldptr) - static_cast(actualptr); + qptrdiff newoffset = reinterpret_cast(faked_ptr) - static_cast(real); + if (oldoffset != newoffset) + memmove(faked_ptr, static_cast(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 -- cgit v1.2.3