Avoid creating wide images with negative bytesPerLine
The QImage API can not handle images with more bytes per line than what an integer can hold. Fixes: QTBUG-73731 Fixes: QTBUG-73732 Change-Id: Ieed6fec7645661fd58d8d25335f806faaa1bb3e9 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
81fd7f4c8a
commit
a5cded843f
@ -124,7 +124,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format)
|
||||
int height = size.height();
|
||||
int depth = qt_depthForFormat(format);
|
||||
auto params = calculateImageParameters(width, height, depth);
|
||||
if (params.bytesPerLine < 0)
|
||||
if (!params.isValid())
|
||||
return nullptr;
|
||||
|
||||
QScopedPointer<QImageData> d(new QImageData);
|
||||
@ -781,7 +781,7 @@ QImageData *QImageData::create(uchar *data, int width, int height, int bpl, QIm
|
||||
|
||||
const int depth = qt_depthForFormat(format);
|
||||
auto params = calculateImageParameters(width, height, depth);
|
||||
if (params.totalSize < 0)
|
||||
if (!params.isValid())
|
||||
return nullptr;
|
||||
|
||||
if (bpl > 0) {
|
||||
@ -1484,10 +1484,17 @@ qsizetype QImage::sizeInBytes() const
|
||||
|
||||
\sa scanLine()
|
||||
*/
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
||||
qsizetype QImage::bytesPerLine() const
|
||||
{
|
||||
return d ? d->bytes_per_line : 0;
|
||||
}
|
||||
#else
|
||||
int QImage::bytesPerLine() const
|
||||
{
|
||||
return d ? d->bytes_per_line : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -227,7 +227,11 @@ public:
|
||||
uchar *scanLine(int);
|
||||
const uchar *scanLine(int) const;
|
||||
const uchar *constScanLine(int) const;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
||||
qsizetype bytesPerLine() const;
|
||||
#else
|
||||
int bytesPerLine() const;
|
||||
#endif
|
||||
|
||||
bool valid(int x, int y) const;
|
||||
bool valid(const QPoint &pt) const;
|
||||
|
@ -109,6 +109,7 @@ struct Q_GUI_EXPORT QImageData { // internal image data
|
||||
struct ImageSizeParameters {
|
||||
qsizetype bytesPerLine;
|
||||
qsizetype totalSize;
|
||||
bool isValid() const { return bytesPerLine > 0 && totalSize > 0; }
|
||||
};
|
||||
static ImageSizeParameters calculateImageParameters(qsizetype width, qsizetype height, qsizetype depth);
|
||||
};
|
||||
@ -135,6 +136,11 @@ QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetyp
|
||||
qsizetype dummy;
|
||||
if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy))
|
||||
return invalid; // why is this here?
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
|
||||
// Disallow images where width * depth calculations might overflow
|
||||
if (width > (INT_MAX - 31) / depth)
|
||||
return invalid;
|
||||
#endif
|
||||
|
||||
return { bytes_per_line, total_size };
|
||||
}
|
||||
|
@ -230,6 +230,8 @@ private slots:
|
||||
|
||||
void convertColorTable();
|
||||
|
||||
void wideImage();
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||
void toWinHBITMAP_data();
|
||||
void toWinHBITMAP();
|
||||
@ -3535,6 +3537,24 @@ void tst_QImage::convertColorTable()
|
||||
QCOMPARE(rgb32.pixel(0,0), 0xffffffff);
|
||||
}
|
||||
|
||||
void tst_QImage::wideImage()
|
||||
{
|
||||
// QTBUG-73731 and QTBUG-73732
|
||||
QImage i(538994187, 2, QImage::Format_ARGB32);
|
||||
QImage i2(32, 32, QImage::Format_ARGB32);
|
||||
i2.fill(Qt::white);
|
||||
|
||||
// Test that it doesn't crash:
|
||||
QPainter painter(&i);
|
||||
// With the composition mode is SourceOver out it's an invalid write
|
||||
// With the composition mode is Source it's an invalid read
|
||||
painter.drawImage(0, 0, i2);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
painter.drawImage(0, 0, i2);
|
||||
|
||||
// Qt6: Test that it actually works on 64bit architectures.
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||
QT_BEGIN_NAMESPACE
|
||||
Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &p, int hbitmapFormat = 0);
|
||||
|
Loading…
Reference in New Issue
Block a user