summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEirik Aavitsland <eirik.aavitsland@qt.io>2020-08-26 09:04:35 +0200
committerEirik Aavitsland <eirik.aavitsland@qt.io>2020-08-27 07:18:40 +0000
commit93466dad6613085a5044a862a3a84a4eba6fcef9 (patch)
treef8fbf6889c6c3608d884b4aa7c12c84d8daef90e
parent103aace3b30ede9e5f5621e14542f5369eac749d (diff)
downloadqtsvg-93466dad6613085a5044a862a3a84a4eba6fcef9.tar.gz
Implement basic format check also for compressed svgs
For uncompressed files, QSvgIOhandler::canRead() will reject any file that does not start out with a svg or xml tag. That rudimentary check was never done for compressed files (svgz). Implement the check during the decompressing itself, so that we can fail early and not waste time and memory decompressing potentially huge files that are anyway not valid svgs. Fixes: oss-fuzz-24611 Pick-to: 5.15 5.12 Change-Id: I154efd8adafe7f09307e8b28a66b536539b1e4bd Reviewed-by: Robert Loehning <robert.loehning@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/svg/qsvgtinydocument.cpp25
1 files changed, 19 insertions, 6 deletions
diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp
index 8e12d5c..3bd0064 100644
--- a/src/svg/qsvgtinydocument.cpp
+++ b/src/svg/qsvgtinydocument.cpp
@@ -73,13 +73,15 @@ QSvgTinyDocument::~QSvgTinyDocument()
}
#ifndef QT_NO_COMPRESS
+static QByteArray qt_inflateSvgzDataFrom(QIODevice *device, bool doCheckContent = true);
# ifdef QT_BUILD_INTERNAL
-Q_AUTOTEST_EXPORT QByteArray qt_inflateGZipDataFrom(QIODevice *device);
-# else
-static QByteArray qt_inflateGZipDataFrom(QIODevice *device);
+Q_AUTOTEST_EXPORT QByteArray qt_inflateGZipDataFrom(QIODevice *device)
+{
+ return qt_inflateSvgzDataFrom(device, false); // autotest wants unchecked result
+}
# endif
-QByteArray qt_inflateGZipDataFrom(QIODevice *device)
+static QByteArray qt_inflateSvgzDataFrom(QIODevice *device, bool doCheckContent)
{
if (!device)
return QByteArray();
@@ -155,6 +157,17 @@ QByteArray qt_inflateGZipDataFrom(QIODevice *device)
// it means we have to provide more data, so exit the loop here
} while (!zlibStream.avail_out);
+ if (doCheckContent) {
+ // Quick format check, equivalent to QSvgIOHandler::canRead()
+ QByteArray buf = destination.left(8);
+ if (!buf.contains("<?xml") && !buf.contains("<svg") && !buf.contains("<!--")) {
+ inflateEnd(&zlibStream);
+ qCWarning(lcSvgHandler, "Error while inflating gzip file: SVG format check failed");
+ return QByteArray();
+ }
+ doCheckContent = false; // Run only once, on first chunk
+ }
+
if (zlibResult == Z_STREAM_END) {
// Make sure there are no more members to process before exiting
if (!(zlibStream.avail_in && inflateReset(&zlibStream) == Z_OK))
@@ -182,7 +195,7 @@ QSvgTinyDocument * QSvgTinyDocument::load(const QString &fileName)
#ifndef QT_NO_COMPRESS
if (fileName.endsWith(QLatin1String(".svgz"), Qt::CaseInsensitive)
|| fileName.endsWith(QLatin1String(".svg.gz"), Qt::CaseInsensitive)) {
- return load(qt_inflateGZipDataFrom(&file));
+ return load(qt_inflateSvgzDataFrom(&file));
}
#endif
@@ -205,7 +218,7 @@ QSvgTinyDocument * QSvgTinyDocument::load(const QByteArray &contents)
// Check for gzip magic number and inflate if appropriate
if (contents.startsWith("\x1f\x8b")) {
QBuffer buffer(const_cast<QByteArray *>(&contents));
- const QByteArray inflated = qt_inflateGZipDataFrom(&buffer);
+ const QByteArray inflated = qt_inflateSvgzDataFrom(&buffer);
if (inflated.isNull())
return nullptr;
return load(inflated);