summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Loew <andreas@code-and-web.de>2012-04-12 08:48:11 (GMT)
committerQt by Nokia <qt-info@nokia.com>2012-04-13 02:23:46 (GMT)
commit3b7edefb5b8a3dd6b1b53af4039cf1a862cd0aed (patch)
treee49cd9d66cd068c5ea0257e7dfa0d4ed9ea69777
parentfbe9f5b96c36b872aa02049d7bda7c4cebfd8edd (diff)
downloadQt-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.cpp57
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)