From 509bc7e59c69937900cf258e64889a6e88edbcf0 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Tue, 3 Mar 2015 09:39:22 +0100 Subject: [PATCH] Fix another crash when converting format of buffer-created QImage This continues 68762151dbf45fbb44e140ac2ad13dbe8d357352 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 --- src/gui/image/qimage_conversions.cpp | 8 ++++++++ tests/auto/gui/image/qimage/tst_qimage.cpp | 12 +++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index b2681f42614..bd40d0d4fc4 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -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; diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index e8da3263aef..309d3a80c5b 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -2456,6 +2456,7 @@ void tst_QImage::inplaceConversion_data() QTest::addColumn("format"); QTest::addColumn("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 }