Skip to content

Commit

Permalink
Fix another crash when converting format of buffer-created QImage
Browse files Browse the repository at this point in the history
This continues 6876215

When doing format conversion, the optimized inplace codepath did not
check if the image data was external, i.e. if the QImage had been
created by the constructor taking an existing external buffer.

The previous commit fixed the readonly case. But in the case of the
QImage constructor taking non-const uchar*, data will be read-write,
but still external. This would of course crash if the converter tries
to realloc it.

Task-number: QTBUG-44610
Change-Id: I94d275d464e8af221682b538fc3e4897a59c061e
Reviewed-by: Allan Sandfeld Jensen <[email protected]>
  • Loading branch information
Eirik Aavitsland committed Mar 4, 2015
1 parent 227bb20 commit 509bc7e
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
8 changes: 8 additions & 0 deletions src/gui/image/qimage_conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,8 @@ static bool convert_BGR30_to_RGB30_inplace(QImageData *data, Qt::ImageConversion
static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_Indexed8);
if (!data->own_data)
return false;
const int depth = 32;

const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
Expand Down Expand Up @@ -768,6 +770,8 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve
static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_Indexed8);
if (!data->own_data)
return false;
const int depth = 32;

const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
Expand Down Expand Up @@ -817,6 +821,8 @@ static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversio
static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_Indexed8);
if (!data->own_data)
return false;
const int depth = 16;

const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
Expand Down Expand Up @@ -872,6 +878,8 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers
static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_RGB32);
if (!data->own_data)
return false;
const int depth = 16;

const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
Expand Down
12 changes: 9 additions & 3 deletions tests/auto/gui/image/qimage/tst_qimage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2456,6 +2456,7 @@ void tst_QImage::inplaceConversion_data()
QTest::addColumn<QImage::Format>("format");
QTest::addColumn<QImage::Format>("dest_format");

QTest::newRow("Format_RGB32 -> RGB16") << QImage::Format_RGB32 << QImage::Format_RGB16;
QTest::newRow("Format_ARGB32 -> Format_RGBA8888") << QImage::Format_ARGB32 << QImage::Format_RGBA8888;
QTest::newRow("Format_RGB888 -> Format_ARGB6666_Premultiplied") << QImage::Format_RGB888 << QImage::Format_ARGB6666_Premultiplied;
QTest::newRow("Format_RGB16 -> Format_RGB555") << QImage::Format_RGB16 << QImage::Format_RGB555;
Expand Down Expand Up @@ -2494,16 +2495,21 @@ void tst_QImage::inplaceConversion()
QCOMPARE(imageConverted.constScanLine(0), originalPtr);

{
// Test attempted inplace conversion of images created on existing, readonly buffer
// Test attempted inplace conversion of images created on existing buffer
static const quint32 readOnlyData[] = { 0x00010203U, 0x04050607U, 0x08091011U, 0x12131415U };
quint32 readWriteData[] = { 0x00010203U, 0x04050607U, 0x08091011U, 0x12131415U };

QImage roImage((const uchar *)readOnlyData, 2, 2, format);
QImage inplaceConverted = std::move(roImage).convertToFormat(dest_format);
QImage roInplaceConverted = std::move(roImage).convertToFormat(dest_format);

QImage rwImage((uchar *)readWriteData, 2, 2, format);
QImage rwInplaceConverted = std::move(rwImage).convertToFormat(dest_format);

QImage roImage2((const uchar *)readOnlyData, 2, 2, format);
QImage normalConverted = roImage2.convertToFormat(dest_format);

QCOMPARE(normalConverted, inplaceConverted);
QCOMPARE(normalConverted, roInplaceConverted);
QCOMPARE(normalConverted, rwInplaceConverted);
}
#endif
}
Expand Down

0 comments on commit 509bc7e

Please sign in to comment.