diff options
author | Andreas Loew <andreas@code-and-web.de> | 2012-04-12 08:48:11 (GMT) |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-04-13 02:23:46 (GMT) |
commit | 3b7edefb5b8a3dd6b1b53af4039cf1a862cd0aed (patch) | |
tree | e49cd9d66cd068c5ea0257e7dfa0d4ed9ea69777 | |
parent | fbe9f5b96c36b872aa02049d7bda7c4cebfd8edd (diff) | |
download | Qt-3b7edefb5b8a3dd6b1b53af4039cf1a862cd0aed.zip Qt-3b7edefb5b8a3dd6b1b53af4039cf1a862cd0aed.tar.gz Qt-3b7edefb5b8a3dd6b1b53af4039cf1a862cd0aed.tar.bz2 |
Fixes crashes and memory leak in QMacPixmapData
QTBUG-24709
QTBUG-24710
QTBUG-24711
Change-Id: I7b4034fae8b3b0ee43eb04ecce3c31479adb3b68
Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
-rwxr-xr-x[-rw-r--r--] | src/gui/image/qpixmap_mac.cpp | 57 |
1 files changed, 44 insertions, 13 deletions
diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp index 4f30107..0a22e87 100644..100755 --- a/src/gui/image/qpixmap_mac.cpp +++ b/src/gui/image/qpixmap_mac.cpp @@ -96,6 +96,11 @@ void qt_mac_cgimage_data_free(void *info, const void *memoryToFree, size_t) } else { if (QMacPixmapData::validDataPointers.contains(pmdata) == false) { free(const_cast<void *>(memoryToFree)); + // mark data as freed + if (pmdata->pixels == memoryToFree) + pmdata->pixels = 0; + if (pmdata->pixelsToFree == memoryToFree) + pmdata->pixelsToFree = 0; return; } if (pmdata->pixels == pmdata->pixelsToFree) { @@ -284,6 +289,10 @@ void QMacPixmapData::fromImage(const QImage &img, // different size or depth, make a new pixmap resize(w, h); + // exit if resize failed + if (is_null) + return; + quint32 *dptr = pixels, *drow; const uint dbpr = bytesPerRow; @@ -379,6 +388,9 @@ QImage QMacPixmapData::toImage() const QImage::Format_RGB32); QImage image(w, h, format); + // exit if image was not created (out of memory) + if (image.isNull()) + return image; quint32 *sptr = pixels, *srow; const uint sbpr = bytesPerRow; if (format == QImage::Format_MonoLSB) { @@ -515,10 +527,11 @@ QMacPixmapData::~QMacPixmapData() delete pengine; // Make sure we aren't drawing on the context anymore. if (cg_data) { CGImageRelease(cg_data); - } else if (!cg_dataBeingReleased && pixels != pixelsToFree) { - free(pixels); } - free(pixelsToFree); + if (pixels && (pixels != pixelsToFree)) + free(pixels); + if (pixelsToFree) + free(pixelsToFree); } void QMacPixmapData::macSetAlphaChannel(const QMacPixmapData *pix, bool asMask) @@ -636,7 +649,7 @@ void QMacPixmapData::macReleaseCGImageRef() // copy them over. This is to preserve the fact that CGImageRef's are immutable. void QMacPixmapData::macCreatePixels() { - const int numBytes = bytesPerRow * h; + int numBytes = bytesPerRow * h; quint32 *base_pixels; if (pixelsToFree && pixelsToFree != pixels) { // Reuse unused block of memory lying around from a previous callback. @@ -645,10 +658,24 @@ void QMacPixmapData::macCreatePixels() } else { // We need a block of memory to do stuff with. base_pixels = static_cast<quint32 *>(malloc(numBytes)); + if (!base_pixels) { + qWarning("Failed to allocate memory for pixmap data, setting to NULL"); + numBytes = 0; + w = 0; + h = 0; + is_null = 0; + bytesPerRow=0; + } } - if (pixels) + // only copy when both buffers exist + if (pixels && base_pixels) memcpy(base_pixels, pixels, qMin(pixelsSize, (uint) numBytes)); + + // free pixels before assigning new memory + if (pixels) + free(pixels); + pixels = base_pixels; pixelsSize = numBytes; } @@ -1174,15 +1201,19 @@ void QMacPixmapData::copy(const QPixmapData *data, const QRect &rect) const int x = rect.x(); const int y = rect.y(); char *dest = reinterpret_cast<char*>(pixels); - const char *src = reinterpret_cast<const char*>(macData->pixels + x) + y * macData->bytesPerRow; - for (int i = 0; i < h; ++i) { - memcpy(dest, src, w * 4); - dest += bytesPerRow; - src += macData->bytesPerRow; - } - has_alpha = macData->has_alpha; - has_mask = macData->has_mask; + // only copy data buffer if destination buffer exists (resize might have failed) + if (dest) { + const char *src = reinterpret_cast<const char*>(macData->pixels + x) + y * macData->bytesPerRow; + for (int i = 0; i < h; ++i) { + memcpy(dest, src, w * 4); + dest += bytesPerRow; + src += macData->bytesPerRow; + } + + has_alpha = macData->has_alpha; + has_mask = macData->has_mask; + } } bool QMacPixmapData::scroll(int dx, int dy, const QRect &rect) |