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>
This commit is contained in:
parent
ceebad9bd2
commit
d1cafa3eba
@ -422,8 +422,11 @@ static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int
|
|||||||
if (info.bmiHeader.biHeight > 0) // Force top-down
|
if (info.bmiHeader.biHeight > 0) // Force top-down
|
||||||
info.bmiHeader.biHeight = -info.bmiHeader.biHeight;
|
info.bmiHeader.biHeight = -info.bmiHeader.biHeight;
|
||||||
info.bmiHeader.biCompression = BI_RGB; // Extract using no compression (can be BI_BITFIELD)
|
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;
|
info.bmiHeader.biBitCount = 32;
|
||||||
|
allocSize = info.bmiHeader.biWidth * qAbs(info.bmiHeader.biHeight) * 4;
|
||||||
|
}
|
||||||
|
|
||||||
const QImage::Format imageFormat = imageFromWinHBITMAP_Format(info.bmiHeader, hbitmapFormat);
|
const QImage::Format imageFormat = imageFromWinHBITMAP_Format(info.bmiHeader, hbitmapFormat);
|
||||||
if (imageFormat == QImage::Format_Invalid) {
|
if (imageFormat == QImage::Format_Invalid) {
|
||||||
@ -431,7 +434,7 @@ static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int
|
|||||||
return QImage();
|
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)) {
|
if (!GetDIBits(displayDc, bitmap, 0, qAbs(info.bmiHeader.biHeight), data.data(), &info, DIB_RGB_COLORS)) {
|
||||||
qErrnoWarning("%s: GetDIBits() failed to get data.", __FUNCTION__);
|
qErrnoWarning("%s: GetDIBits() failed to get data.", __FUNCTION__);
|
||||||
return QImage();
|
return QImage();
|
||||||
|
@ -233,6 +233,7 @@ private slots:
|
|||||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||||
void toWinHBITMAP_data();
|
void toWinHBITMAP_data();
|
||||||
void toWinHBITMAP();
|
void toWinHBITMAP();
|
||||||
|
void fromMonoHBITMAP();
|
||||||
#endif // Q_OS_WIN && !Q_OS_WINRT
|
#endif // Q_OS_WIN && !Q_OS_WINRT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -3635,6 +3636,19 @@ void tst_QImage::toWinHBITMAP()
|
|||||||
DeleteDC(bitmapDc);
|
DeleteDC(bitmapDc);
|
||||||
ReleaseDC(0, displayDc);
|
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
|
#endif // Q_OS_WIN && !Q_OS_WINRT
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(tst_QImage)
|
QTEST_GUILESS_MAIN(tst_QImage)
|
||||||
|
Loading…
Reference in New Issue
Block a user