summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2018-12-12 10:46:32 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2018-12-12 16:08:10 +0000
commitd1cafa3ebac00f60cab3ca2beed6ebf2e6579a94 (patch)
treeab324285e68defa3c1641337ca21dd741e01e890
parentceebad9bd2c5ca35c09a17b0adc5e8ee140bdad2 (diff)
qt_imageFromWinHBITMAP(): Fix memory corruption when converting from bitmaps with low depths
Insufficient memory was allocated when asking GetDIBits() to convert to 32bit. Fix allocation size and use a QScopedArrayPointer. Fixes: QTBUG-72343 Change-Id: I45f79c913a243316e01bc6efed08e50ccc7d25f4 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
-rw-r--r--src/gui/image/qpixmap_win.cpp7
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp14
2 files changed, 19 insertions, 2 deletions
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index b8d13ac092..b5f8d43041 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -422,8 +422,11 @@ static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int
if (info.bmiHeader.biHeight > 0) // Force top-down
info.bmiHeader.biHeight = -info.bmiHeader.biHeight;
info.bmiHeader.biCompression = BI_RGB; // Extract using no compression (can be BI_BITFIELD)
- if (forceQuads)
+ size_t allocSize = info.bmiHeader.biSizeImage;
+ if (forceQuads) {
info.bmiHeader.biBitCount = 32;
+ allocSize = info.bmiHeader.biWidth * qAbs(info.bmiHeader.biHeight) * 4;
+ }
const QImage::Format imageFormat = imageFromWinHBITMAP_Format(info.bmiHeader, hbitmapFormat);
if (imageFormat == QImage::Format_Invalid) {
@@ -431,7 +434,7 @@ static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int
return QImage();
}
- QScopedPointer<uchar> data(new uchar[info.bmiHeader.biSizeImage]);
+ QScopedArrayPointer<uchar> data(new uchar[allocSize]);
if (!GetDIBits(displayDc, bitmap, 0, qAbs(info.bmiHeader.biHeight), data.data(), &info, DIB_RGB_COLORS)) {
qErrnoWarning("%s: GetDIBits() failed to get data.", __FUNCTION__);
return QImage();
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index 5ffd75f931..eded206d37 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -233,6 +233,7 @@ private slots:
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
void toWinHBITMAP_data();
void toWinHBITMAP();
+ void fromMonoHBITMAP();
#endif // Q_OS_WIN && !Q_OS_WINRT
private:
@@ -3635,6 +3636,19 @@ void tst_QImage::toWinHBITMAP()
DeleteDC(bitmapDc);
ReleaseDC(0, displayDc);
}
+
+void tst_QImage::fromMonoHBITMAP() // QTBUG-72343, corruption for mono bitmaps
+{
+ enum : int { width = 32, height = 32, size = width * height / 8 }; // 32x32 mono bitmap
+ char bitmapData[size];
+ memset(bitmapData, 0, size);
+ const HBITMAP hbitmap = CreateBitmap(width, height, /* planes */ 1, /* bitcount */ 1, bitmapData);
+ const QImage image = qt_imageFromWinHBITMAP(hbitmap);
+ QCOMPARE(image.size(), QSize(width, height));
+ QCOMPARE(image.scanLine(0)[0], 0u);
+ DeleteObject(hbitmap);
+}
+
#endif // Q_OS_WIN && !Q_OS_WINRT
QTEST_GUILESS_MAIN(tst_QImage)