summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-28 11:20:27 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-03-04 09:05:30 +0000
commit6f152f87dbbd47acc58458d636ce5d1cc181b8fd (patch)
tree6ddeebfb1078c205cba8a86c315e2e961e1b6b0e
parentf354d4be9a7a436fb16bd9764a261c930101850c (diff)
downloadqtsvg-6f152f87dbbd47acc58458d636ce5d1cc181b8fd.tar.gz
Fix IRI parsing, and use after free
Make the parsing of IRI references tighter, and avoid freeing styles when inserting a duplicate id. Fixes: QTBUG-74104 Change-Id: I3a12fcf09ce1c55c135a4209817413ed8af75dec Reviewed-by: Robert Loehning <robert.loehning@qt.io> Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
-rw-r--r--src/svg/qsvghandler.cpp14
-rw-r--r--src/svg/qsvgtinydocument.cpp5
-rw-r--r--tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp39
3 files changed, 45 insertions, 13 deletions
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index 463ec01..599ed56 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -774,21 +774,31 @@ static QVector<qreal> parsePercentageList(const QChar *&str)
static QString idFromUrl(const QString &url)
{
+ // The form is url(<IRI>), where IRI can be
+ // just an ID on #<id> form.
QString::const_iterator itr = url.constBegin();
QString::const_iterator end = url.constEnd();
+ QString id;
while (itr != end && (*itr).isSpace())
++itr;
if (itr != end && (*itr) == QLatin1Char('('))
++itr;
+ else
+ return QString();
while (itr != end && (*itr).isSpace())
++itr;
- if (itr != end && (*itr) == QLatin1Char('#'))
+ if (itr != end && (*itr) == QLatin1Char('#')) {
+ id += *itr;
++itr;
- QString id;
+ } else {
+ return QString();
+ }
while (itr != end && (*itr) != QLatin1Char(')')) {
id += *itr;
++itr;
}
+ if (itr == end || (*itr) != QLatin1Char(')'))
+ return QString();
return id;
}
diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp
index 813395f..da464cc 100644
--- a/src/svg/qsvgtinydocument.cpp
+++ b/src/svg/qsvgtinydocument.cpp
@@ -363,7 +363,10 @@ QSvgNode *QSvgTinyDocument::namedNode(const QString &id) const
void QSvgTinyDocument::addNamedStyle(const QString &id, QSvgFillStyleProperty *style)
{
- m_namedStyles.insert(id, style);
+ if (!m_namedStyles.contains(id))
+ m_namedStyles.insert(id, style);
+ else
+ qCWarning(lcSvgHandler) << "Duplicate unique style id:" << id;
}
QSvgFillStyleProperty *QSvgTinyDocument::namedStyle(const QString &id) const
diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
index 553838e..5b359b9 100644
--- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
+++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
@@ -77,6 +77,7 @@ private slots:
void testUseElement();
void smallFont();
void styleSheet();
+ void duplicateStyleId();
#ifndef QT_NO_COMPRESS
void testGzLoading();
@@ -139,22 +140,28 @@ void tst_QSvgRenderer::invalidUrl_data()
{
QTest::addColumn<QByteArray>("svg");
- QTest::newRow("00") << QByteArray("<svg><circle fill=\"url\" /></svg>");
- QTest::newRow("01") << QByteArray("<svg><circle fill=\"url0\" /></svg>");
- QTest::newRow("02") << QByteArray("<svg><circle fill=\"url(0\" /></svg>");
- QTest::newRow("03") << QByteArray("<svg><circle fill=\"url (0\" /></svg>");
- QTest::newRow("04") << QByteArray("<svg><circle fill=\"url ( 0\" /></svg>");
- QTest::newRow("05") << QByteArray("<svg><circle fill=\"url#\" /></svg>");
- QTest::newRow("06") << QByteArray("<svg><circle fill=\"url#(\" /></svg>");
- QTest::newRow("07") << QByteArray("<svg><circle fill=\"url(#\" /></svg>");
- QTest::newRow("08") << QByteArray("<svg><circle fill=\"url(# \" /></svg>");
- QTest::newRow("09") << QByteArray("<svg><circle fill=\"url(# 0\" /></svg>");
+ QTest::newRow("01") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url0\" /></svg>");
+ QTest::newRow("02") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url(0\" /></svg>");
+ QTest::newRow("03") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url (0\" /></svg>");
+ QTest::newRow("04") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url ( 0\" /></svg>");
+ QTest::newRow("05") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url#\" /></svg>");
+ QTest::newRow("06") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url#(\" /></svg>");
+ QTest::newRow("07") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url(#\" /></svg>");
+ QTest::newRow("08") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url(# \" /></svg>");
+ QTest::newRow("09") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url(# 0\" /></svg>");
+ QTest::newRow("10") << QByteArray("<svg><linearGradient id=\"blabla\"/><circle fill=\"urlblabla\" /></svg>");
+ QTest::newRow("11") << QByteArray("<svg><linearGradient id=\"blabla\"/><circle fill=\"url(blabla\" /></svg>");
+ QTest::newRow("12") << QByteArray("<svg><linearGradient id=\"blabla\"/><circle fill=\"url(blabla)\" /></svg>");
+ QTest::newRow("13") << QByteArray("<svg><linearGradient id=\"blabla\"/><circle fill=\"url(#blabla\" /></svg>");
}
void tst_QSvgRenderer::invalidUrl()
{
QFETCH(QByteArray, svg);
+#if QT_CONFIG(regularexpression)
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Could not resolve property"));
+#endif
QSvgRenderer renderer(svg);
QVERIFY(renderer.isValid());
}
@@ -1459,5 +1466,17 @@ void tst_QSvgRenderer::styleSheet()
QCOMPARE(images[0], images[1]);
}
+void tst_QSvgRenderer::duplicateStyleId()
+{
+ QByteArray svg = QByteArrayLiteral("<svg><linearGradient id=\"a\"/>"
+ "<rect style=\"fill:url(#a)\"/>"
+ "<linearGradient id=\"a\"/></svg>");
+ QTest::ignoreMessage(QtWarningMsg, "Duplicate unique style id: \"a\"");
+ QImage image(200, 200, QImage::Format_RGB32);
+ QPainter painter(&image);
+ QSvgRenderer renderer(svg);
+ renderer.render(&painter);
+}
+
QTEST_MAIN(tst_QSvgRenderer)
#include "tst_qsvgrenderer.moc"