|
| 1 | +From 40e56c7fd9c3b2da25f64d63865cd014867e0be9 Mon Sep 17 00:00:00 2001 |
| 2 | +From: AllSpark < [email protected]> |
| 3 | +Date: Tue, 7 Oct 2025 06:28:14 +0000 |
| 4 | +Subject: [PATCH] Backport: Avoid creating and deleting misplaced group nodes; |
| 5 | + add test for misplaced element causing dangling reference. |
| 6 | + |
| 7 | +Signed-off-by: Azure Linux Security Servicing Account < [email protected]> |
| 8 | +Upstream-reference: AI Backport of https://code.qt.io/cgit/qt/qtsvg.git/patch/?id=6a6273126770006232e805cf1631f93d4919b788 |
| 9 | +--- |
| 10 | + src/svg/qsvghandler.cpp | 20 ++++++++------- |
| 11 | + tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 27 ++++++++++++++++++++ |
| 12 | + 2 files changed, 38 insertions(+), 9 deletions(-) |
| 13 | + |
| 14 | +diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp |
| 15 | +index 335500a..e6c07d7 100644 |
| 16 | +--- a/src/svg/qsvghandler.cpp |
| 17 | ++++ b/src/svg/qsvghandler.cpp |
| 18 | +@@ -3727,11 +3727,12 @@ bool QSvgHandler::startElement(const QString &localName, |
| 19 | + |
| 20 | + if (FactoryMethod method = findGroupFactory(localName)) { |
| 21 | + //group |
| 22 | +- node = method(m_doc ? m_nodes.top() : 0, attributes, this); |
| 23 | +- Q_ASSERT(node); |
| 24 | + if (!m_doc) { |
| 25 | +- Q_ASSERT(node->type() == QSvgNode::DOC); |
| 26 | +- m_doc = static_cast<QSvgTinyDocument*>(node); |
| 27 | ++ node = method(nullptr, attributes, this); |
| 28 | ++ if (node) { |
| 29 | ++ Q_ASSERT(node->type() == QSvgNode::DOC); |
| 30 | ++ m_doc = static_cast<QSvgTinyDocument*>(node); |
| 31 | ++ } |
| 32 | + } else { |
| 33 | + switch (m_nodes.top()->type()) { |
| 34 | + case QSvgNode::DOC: |
| 35 | +@@ -3739,16 +3740,17 @@ bool QSvgHandler::startElement(const QString &localName, |
| 36 | + case QSvgNode::DEFS: |
| 37 | + case QSvgNode::SWITCH: |
| 38 | + { |
| 39 | +- QSvgStructureNode *group = |
| 40 | +- static_cast<QSvgStructureNode*>(m_nodes.top()); |
| 41 | +- group->addChild(node, someId(attributes)); |
| 42 | ++ node = method(m_nodes.top(), attributes, this); |
| 43 | ++ if (node) { |
| 44 | ++ QSvgStructureNode *group = |
| 45 | ++ static_cast<QSvgStructureNode*>(m_nodes.top()); |
| 46 | ++ group->addChild(node, someId(attributes)); |
| 47 | ++ } |
| 48 | + } |
| 49 | + break; |
| 50 | + default: |
| 51 | + const QByteArray msg = QByteArrayLiteral("Could not add child element to parent element because the types are incorrect."); |
| 52 | + qCWarning(lcSvgHandler, "%s", prefixMessage(msg, xml).constData()); |
| 53 | +- delete node; |
| 54 | +- node = 0; |
| 55 | + break; |
| 56 | + } |
| 57 | + } |
| 58 | +diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp |
| 59 | +index ec67a2b..c92e3b1 100644 |
| 60 | +--- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp |
| 61 | ++++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp |
| 62 | +@@ -66,6 +66,7 @@ private slots: |
| 63 | + void illegalAnimateTransform(); |
| 64 | + void tSpanLineBreak(); |
| 65 | + |
| 66 | ++ void testMisplacedElement(); |
| 67 | + #ifndef QT_NO_COMPRESS |
| 68 | + void testGzLoading(); |
| 69 | + void testGzHelper_data(); |
| 70 | +@@ -1691,6 +1692,32 @@ void tst_QSvgRenderer::imageRendering() { |
| 71 | + p2.end(); |
| 72 | + QCOMPARE(img1, img2); |
| 73 | + } |
| 74 | ++ |
| 75 | ++void tst_QSvgRenderer::testMisplacedElement() |
| 76 | ++{ |
| 77 | ++ // This input caused a QSvgPattern node to be created with a QSvgPatternStyle referencing to it. |
| 78 | ++ // The code then detected that the <pattern> element is misplaced in the <text> element and |
| 79 | ++ // deleted it. That left behind the QSvgPatternStyle pointing to the deleted QSvgPattern. That |
| 80 | ++ // was reported when running the test with ASAN or UBSAN. |
| 81 | ++ QByteArray svg(R"(<svg> |
| 82 | ++ <text><pattern id="ptn" width="4" height="4"/></text> |
| 83 | ++ <g fill="url(#ptn) "/> |
| 84 | ++ </svg>)"); |
| 85 | ++ |
| 86 | ++ QImage image(20, 20, QImage::Format_ARGB32_Premultiplied); |
| 87 | ++ image.fill(Qt::green); |
| 88 | ++ QImage refImage = image.copy(); |
| 89 | ++ |
| 90 | ++ QTest::ignoreMessage(QtWarningMsg, "<input>:2:68: Could not add child element to parent " |
| 91 | ++ "element because the types are incorrect."); |
| 92 | ++ QTest::ignoreMessage(QtWarningMsg, "<input>:4:28: Could not resolve property: #ptn"); |
| 93 | ++ |
| 94 | ++ QSvgRenderer renderer(svg); |
| 95 | ++ QPainter painter(&image); |
| 96 | ++ renderer.render(&painter); |
| 97 | ++ QCOMPARE(image, refImage); |
| 98 | ++} |
| 99 | ++ |
| 100 | + } |
| 101 | + |
| 102 | + void tst_QSvgRenderer::illegalAnimateTransform_data() |
| 103 | +-- |
| 104 | +2.45.4 |
| 105 | + |
0 commit comments