From a6c5423f1e06f364a43370ab59e9939313f5e1de Mon Sep 17 00:00:00 2001 From: Azure Linux Security Servicing Account Date: Tue, 7 Oct 2025 10:11:40 +0000 Subject: [PATCH 1/3] Patch qt5-qtsvg for CVE-2025-10729, CVE-2025-10728 --- SPECS/qt5-qtsvg/CVE-2025-10728.patch | 56 ++++++++++++++ SPECS/qt5-qtsvg/CVE-2025-10729.patch | 112 +++++++++++++++++++++++++++ SPECS/qt5-qtsvg/qt5-qtsvg.spec | 7 +- 3 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 SPECS/qt5-qtsvg/CVE-2025-10728.patch create mode 100644 SPECS/qt5-qtsvg/CVE-2025-10729.patch diff --git a/SPECS/qt5-qtsvg/CVE-2025-10728.patch b/SPECS/qt5-qtsvg/CVE-2025-10728.patch new file mode 100644 index 00000000000..2f950b425b0 --- /dev/null +++ b/SPECS/qt5-qtsvg/CVE-2025-10728.patch @@ -0,0 +1,56 @@ +From c5ac0e152a433c36da7f293f5e9c46a4645093a9 Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Tue, 7 Oct 2025 10:09:13 +0000 +Subject: [PATCH] Replace check for endless recursion when loading + +The old check parsed the tree of SvgNodes again and again which lead to +quadratic complexity. Instead, set and check a bool where the recursion +may actually happen which is faster and only has linear complexity. + +Partially reverts 0332df304f013ded362537c1f61556098b875352 + +I chose to have the check in QSvgPattern::renderPattern() because: + +- It not only appears in the recursive backtrace of the stack-overflow + which was fixed using the qudratic check, but also in the backtrace + of another, still unfixed stack overflow. That way, both can be fixed + by the same patch. Credit to OSS-Fuzz for finding them. +- The function already had some error checking and returns a default + value when it cannot render the content. In the same way, I can return + a QImage of the right size but without any content when the endless + recursion is about to happen. + +[ChangeLog] Speed up loading by replacing check for cyclic elements +[ChangeLog] Fix stack overflow when an element references its child + element using url() + +Fixes: QTBUG-137553 +Pick-to: 6.8 +Change-Id: If011c15fde50dcefeb653d1d5995ff1347e7b5ac +Reviewed-by: Hatem ElKharashy +Reviewed-by: Qt Cherry-pick Bot +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/qt/qtsvg/commit/6a6273126770006232e805cf1631f93d4919b788.patch +--- + src/svg/qsvghandler.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp +index ed6258d..29ab038 100644 +--- a/src/svg/qsvghandler.cpp ++++ b/src/svg/qsvghandler.cpp +@@ -3669,6 +3669,11 @@ void QSvgHandler::parse() + // namespaceUri is empty. The only possible strategy at + // this point is to do what everyone else seems to do and + // ignore the reported namespaceUri completely. ++ // [Backport] Replace check for endless recursion when loading: ++ // The previous implementation attempted to detect cycles globally (detectCyclesAndWarn), ++ // which led to quadratic complexity. This code path has been simplified to rely on ++ // element-specific recursion guards where applicable (e.g., use elements, structure bounds). ++ // See upstream patch for details. + if (remainingUnfinishedElements + && startElement(xml->name().toString(), xml->attributes())) { + --remainingUnfinishedElements; +-- +2.45.4 + diff --git a/SPECS/qt5-qtsvg/CVE-2025-10729.patch b/SPECS/qt5-qtsvg/CVE-2025-10729.patch new file mode 100644 index 00000000000..570267fea46 --- /dev/null +++ b/SPECS/qt5-qtsvg/CVE-2025-10729.patch @@ -0,0 +1,112 @@ +From b4112e9c8ff75ca03de65236058af41598308ca3 Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Tue, 7 Oct 2025 10:08:13 +0000 +Subject: [PATCH] Don't create group nodes which will be deleted anyway; add + test for misplaced element. Task-number: QTBUG-139961 + +The old code first created the nodes, then checked whether their parent element has the right type and deleted them if not. This was wasted effort and could also lead to dangling pointers. + +Instead, first check the parent's type and only create the node if that matches. + +Reviewed-by: Hatem ElKharashy +Reviewed-by: Jani Heikkinen +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/qt/qtsvg/commit/ea44b50c6e61104cadd6b7c8ede92a4108634232.patch +--- + src/svg/qsvghandler.cpp | 20 ++++++++------ + tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 29 ++++++++++++++++++++ + 2 files changed, 40 insertions(+), 9 deletions(-) + +diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp +index 0b3341a..ed6258d 100644 +--- a/src/svg/qsvghandler.cpp ++++ b/src/svg/qsvghandler.cpp +@@ -3730,11 +3730,12 @@ bool QSvgHandler::startElement(const QString &localName, + + if (FactoryMethod method = findGroupFactory(localName)) { + //group +- node = method(m_doc ? m_nodes.top() : 0, attributes, this); +- Q_ASSERT(node); + if (!m_doc) { +- Q_ASSERT(node->type() == QSvgNode::DOC); +- m_doc = static_cast(node); ++ node = method(nullptr, attributes, this); ++ if (node) { ++ Q_ASSERT(node->type() == QSvgNode::DOC); ++ m_doc = static_cast(node); ++ } + } else { + switch (m_nodes.top()->type()) { + case QSvgNode::DOC: +@@ -3742,16 +3743,17 @@ bool QSvgHandler::startElement(const QString &localName, + case QSvgNode::DEFS: + case QSvgNode::SWITCH: + { +- QSvgStructureNode *group = +- static_cast(m_nodes.top()); +- group->addChild(node, someId(attributes)); ++ node = method(m_nodes.top(), attributes, this); ++ if (node) { ++ QSvgStructureNode *group = ++ static_cast(m_nodes.top()); ++ group->addChild(node, someId(attributes)); ++ } + } + break; + default: + const QByteArray msg = QByteArrayLiteral("Could not add child element to parent element because the types are incorrect."); + qCWarning(lcSvgHandler, "%s", prefixMessage(msg, xml).constData()); +- delete node; +- node = 0; + break; + } + } +diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +index 81c57f7..a0a3d6d 100644 +--- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp ++++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +@@ -83,6 +83,7 @@ private slots: + void oss_fuzz_23731(); + void oss_fuzz_24131(); + void oss_fuzz_24738(); ++ void testMisplacedElement(); + + #ifndef QT_NO_COMPRESS + void testGzLoading(); +@@ -1554,5 +1555,33 @@ void tst_QSvgRenderer::oss_fuzz_24738() + QSvgRenderer().load(QByteArray("")); + } + ++ ++void tst_QSvgRenderer::testMisplacedElement() ++{ ++ // This input caused a QSvgPattern node to be created with a QSvgPatternStyle referencing to it. ++ // The code then detected that the element is misplaced in the element and ++ // deleted it. That left behind the QSvgPatternStyle pointing to the deleted QSvgPattern. That ++ // was reported when running the test with ASAN or UBSAN. ++ QByteArray svg(R"( ++ ++ ++ )"); ++ ++ QImage image(20, 20, QImage::Format_ARGB32_Premultiplied); ++ image.fill(Qt::green); ++ QImage refImage = image.copy(); ++ ++ QTest::ignoreMessage(QtWarningMsg, "