diff options
author | Liang Qi <liang.qi@qt.io> | 2016-12-08 08:20:36 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-12-08 08:20:36 +0100 |
commit | cae32bd04d117ba2423a8c4db12f8d2d5b809bcb (patch) | |
tree | 179cc91b4b34b9e7ec587d576e42d89fc13fec43 /src/plugins/imageformats/jpeg | |
parent | e1a70ce495928e8d81e80b11d7dbd4c4913ee438 (diff) | |
parent | 04f68053df5c90dca6947c6d2a5bb4e6851e62bb (diff) |
Merge remote-tracking branch 'origin/5.7' into 5.8.0
Change-Id: I576187a9905802c177ae483e6c29d0f55cf7034d
Diffstat (limited to 'src/plugins/imageformats/jpeg')
-rw-r--r-- | src/plugins/imageformats/jpeg/qjpeghandler.cpp | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp index d89b8d398b..68619928d3 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp +++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp @@ -767,6 +767,10 @@ static bool readExifHeader(QDataStream &stream) */ static int getExifOrientation(QByteArray &exifData) { + // Current EXIF version (2.3) says there can be at most 5 IFDs, + // byte we allow for 10 so we're able to deal with future extensions. + const int maxIfdCount = 10; + QDataStream stream(&exifData, QIODevice::ReadOnly); if (!readExifHeader(stream)) @@ -774,7 +778,8 @@ static int getExifOrientation(QByteArray &exifData) quint16 val; quint32 offset; - const qint64 headerStart = stream.device()->pos(); + const qint64 headerStart = 6; // the EXIF header has a constant size + Q_ASSERT(headerStart == stream.device()->pos()); // read byte order marker stream >> val; @@ -785,7 +790,7 @@ static int getExifOrientation(QByteArray &exifData) else return -1; // unknown byte order - // read size + // confirm byte order stream >> val; if (val != 0x2a) return -1; @@ -793,18 +798,22 @@ static int getExifOrientation(QByteArray &exifData) stream >> offset; // read IFD - while (!stream.atEnd()) { + for (int n = 0; n < maxIfdCount; ++n) { quint16 numEntries; - // skip offset bytes to get the next IFD const qint64 bytesToSkip = offset - (stream.device()->pos() - headerStart); - - if (stream.skipRawData(bytesToSkip) != bytesToSkip) + if (bytesToSkip < 0 || (offset + headerStart >= exifData.size())) { + // disallow going backwards, though it's permitted in the spec return -1; + } else if (bytesToSkip != 0) { + // seek to the IFD + if (!stream.device()->seek(offset + headerStart)) + return -1; + } stream >> numEntries; - for (; numEntries > 0; --numEntries) { + for (; numEntries > 0 && stream.status() == QDataStream::Ok; --numEntries) { quint16 tag; quint16 type; quint32 components; @@ -828,12 +837,14 @@ static int getExifOrientation(QByteArray &exifData) // read offset to next IFD stream >> offset; + if (stream.status() != QDataStream::Ok) + return -1; if (offset == 0) // this is the last IFD - break; + return 0; // No Exif orientation was found } - // No Exif orientation was found - return 0; + // too many IFDs + return -1; } static QImageIOHandler::Transformations exif2Qt(int exifOrientation) |