Fix another crash when converting format of buffer-created QImage

This continues 68762151db

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 <allan.jensen@theqtcompany.com>
This commit is contained in:
Eirik Aavitsland 2015-03-03 09:39:22 +01:00 committed by aavit
parent 227bb20ded
commit 509bc7e59c
2 changed files with 17 additions and 3 deletions

View File

@ -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;
@ -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;
@ -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;
@ -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;

View File

@ -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;
@ -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
}