Fix loading of image files with wrong, but known, file name extension

If QImageReader recognized the suffix of a file, it would by default
not check if the file contents matched the claimed format. Hence, a
valid but misnamed image file would fail to load.
Fix by adding contents check for suffix-recognized files.

[ChangeLog][QtGui][Image] Loading of image files having a file name
suffix for a different image file type has been fixed. QImageReader
will now ask the suffix format handler to confirm the file contents
(canRead()), and fall back to normal file content recognition on
failure. This implies a slight behavior change in
QImageReader::loopCount(), ::imageCount() and ::nextImageDelay(): For
an unreadable file with a recognized suffix, they would earlier return
0, while they now will return -1, i.e. error as per the documentation.

Fixes: QTBUG-42540
Fixes: QTBUG-68787
Change-Id: I205e83f29ed7190cbcae95dab960232544d012f6
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
bb10
Eirik Aavitsland 2019-01-11 15:57:56 +01:00
parent 7f948d9eff
commit 82aabafada
2 changed files with 29 additions and 6 deletions

View File

@ -197,7 +197,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
#ifdef QIMAGEREADER_DEBUG
qDebug() << "QImageReader::createReadHandler( device =" << (void *)device << ", format =" << format << "),"
<< keyMap.size() << "plugins available: " << keyMap.values();
<< keyMap.uniqueKeys().size() << "plugins available: " << keyMap;
#endif
int suffixPluginIndex = -1;
@ -325,6 +325,29 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
#endif
}
if (handler && device && !suffix.isEmpty()) {
Q_ASSERT(qobject_cast<QFile *>(device));
// We have a file claiming to be of a recognized format. Now confirm that
// the handler also recognizes the file contents.
const qint64 pos = device->pos();
handler->setDevice(device);
if (!form.isEmpty())
handler->setFormat(form);
bool canRead = handler->canRead();
device->seek(pos);
if (canRead) {
// ok, we're done.
return handler;
}
#ifdef QIMAGEREADER_DEBUG
qDebug() << "QImageReader::createReadHandler: the" << suffix << "handler can not read this file";
#endif
// File may still be valid, just with wrong suffix, so fall back to
// finding a handler based on contents, below.
delete handler;
handler = nullptr;
}
#ifndef QT_NO_IMAGEFORMATPLUGIN
if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) {
// check if any of our plugins recognize the file from its contents.
@ -336,7 +359,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
if (plugin && plugin->capabilities(device, QByteArray()) & QImageIOPlugin::CanRead) {
handler = plugin->create(device, testFormat);
#ifdef QIMAGEREADER_DEBUG
qDebug() << "QImageReader::createReadHandler: the" << keyMap.keys().at(i) << "plugin can read this data";
qDebug() << "QImageReader::createReadHandler: the" << keyMap.value(i) << "plugin can read this data";
#endif
break;
}

View File

@ -164,7 +164,7 @@ void tst_QIcoImageFormat::imageCount_data()
QTest::newRow("16px,32px - 16 colors") << "valid/TIMER01.ICO" << 2;
QTest::newRow("16px16c, 32px32c, 32px256c 1") << "valid/WORLD.ico" << 3;
QTest::newRow("16px16c, 32px32c, 32px256c 2") << "valid/WORLDH.ico" << 3;
QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << 0;
QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << -1;
QTest::newRow("includes 32BPP w/alpha") << "valid/semitransparent.ico" << 9;
QTest::newRow("PNG compression") << "valid/Qt.ico" << 4;
QTest::newRow("CUR file") << "valid/yellow.cur" << 1;
@ -177,7 +177,6 @@ void tst_QIcoImageFormat::imageCount()
QImageReader reader(m_IconPath + QLatin1Char('/') + fileName);
QCOMPARE(reader.imageCount(), count);
}
void tst_QIcoImageFormat::jumpToNextImage_data()
@ -218,7 +217,7 @@ void tst_QIcoImageFormat::loopCount_data()
QTest::addColumn<int>("count");
QTest::newRow("floppy (16px,32px - 16 colors)") << "valid/35FLOPPY.ICO" << 0;
QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << 0;
QTest::newRow("invalid floppy (first 8 bytes = 0xff)") << "invalid/35floppy.ico" << -1;
}
void tst_QIcoImageFormat::loopCount()
@ -228,6 +227,7 @@ void tst_QIcoImageFormat::loopCount()
QImageReader reader(m_IconPath + QLatin1Char('/') + fileName);
QCOMPARE(reader.loopCount(), count);
QCOMPARE(reader.canRead(), count < 0 ? false : true);
}
void tst_QIcoImageFormat::nextImageDelay_data()
@ -256,7 +256,7 @@ void tst_QIcoImageFormat::nextImageDelay()
QImageReader reader(m_IconPath + QLatin1Char('/') + fileName);
if (count == -1) {
QCOMPARE(reader.nextImageDelay(), 0);
QCOMPARE(reader.nextImageDelay(), -1);
} else {
int i;
for (i = 0; i < count; i++) {