Compare commits

...

2 Commits
c10s ... c10

Author SHA1 Message Date
1f7866e887 import OL qt6-qtsvg-6.9.1-2.el10_1.2 2025-12-04 09:11:47 +00:00
a34ccaf034 import OL qt6-qtsvg-6.8.1-1.el10_0.1 2025-11-06 07:35:39 +00:00
7 changed files with 273 additions and 47 deletions

31
.gitignore vendored
View File

@ -1,30 +1 @@
/qtsvg-everywhere-src-6.0.0.tar.xz
/qtsvg-everywhere-src-6.0.1.tar.xz
/qtsvg-everywhere-src-6.0.3.tar.xz
/qtsvg-everywhere-src-6.1.0.tar.xz
/qtsvg-everywhere-src-6.1.1.tar.xz
/qtsvg-everywhere-src-6.1.2.tar.xz
/qtsvg-everywhere-src-6.2.0-beta4.tar.xz
/qtsvg-everywhere-src-6.2.0-rc.tar.xz
/qtsvg-everywhere-src-6.2.0-rc2.tar.xz
/qtsvg-everywhere-src-6.2.0.tar.xz
/qtsvg-everywhere-src-6.2.1.tar.xz
/qtsvg-everywhere-src-6.2.2.tar.xz
/qtsvg-everywhere-src-6.2.3.tar.xz
/qtsvg-everywhere-src-6.3.0.tar.xz
/qtsvg-everywhere-src-6.3.1.tar.xz
/qtsvg-everywhere-src-6.4.0.tar.xz
/qtsvg-everywhere-src-6.4.1.tar.xz
/qtsvg-everywhere-src-6.4.2.tar.xz
/qtsvg-everywhere-src-6.4.3.tar.xz
/qtsvg-everywhere-src-6.5.0.tar.xz
/qtsvg-everywhere-src-6.5.1.tar.xz
/qtsvg-everywhere-src-6.5.2.tar.xz
/qtsvg-everywhere-src-6.5.3.tar.xz
/qtsvg-everywhere-src-6.6.0.tar.xz
/qtsvg-everywhere-src-6.6.1.tar.xz
/qtsvg-everywhere-src-6.7.0.tar.xz
/qtsvg-everywhere-src-6.7.1.tar.xz
/qtsvg-everywhere-src-6.8.1.tar.xz
/qtsvg-everywhere-src-6.9.0.tar.xz
/qtsvg-everywhere-src-6.9.1.tar.xz
qtsvg-everywhere-src-6.9.1.tar.xz

View File

@ -1,3 +0,0 @@
# qt6-qtsvg
The qt6-qtsvg package

152
RHEL-119699.patch Normal file
View File

@ -0,0 +1,152 @@
From ca3bf8db654a2c71166ca8d1fbd3e3e582bd2a45 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Robert=20L=C3=B6hning?= <robert.loehning@qt.io>
Date: Fri, 12 Sep 2025 21:22:58 +0200
Subject: [PATCH] Don't create group nodes which will be deleted anyway
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.
Task-number: QTBUG-139961
Pick-to: 6.8
Change-Id: Ifa870efbd5f336b34b81aa09b6fe79fb7fc826b9
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
(cherry picked from commit 7e8898903265d931df0aa54b3913f2c49d4d7bf2)
Reviewed-by: Jani Heikkinen <jani.heikkinen@qt.io>
(cherry picked from commit 16a8eb2c88ec1125c897da35b524a18d619eb261)
---
src/svg/qsvghandler.cpp | 60 ++++++++++----------
tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 26 +++++++++
2 files changed, 56 insertions(+), 30 deletions(-)
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index cac0be1..2bd14c8 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -4718,46 +4718,46 @@ bool QSvgHandler::startElement(const QString &localName,
if (FactoryMethod method = findGroupFactory(localName, options())) {
//group
- node = method(m_doc ? m_nodes.top() : 0, attributes, this);
-
- if (node) {
- if (!m_doc) {
+ if (!m_doc) {
+ node = method(nullptr, attributes, this);
+ if (node) {
Q_ASSERT(node->type() == QSvgNode::Doc);
m_doc = static_cast<QSvgTinyDocument*>(node);
- } else {
- switch (m_nodes.top()->type()) {
- case QSvgNode::Doc:
- case QSvgNode::Group:
- case QSvgNode::Defs:
- case QSvgNode::Switch:
- case QSvgNode::Mask:
- case QSvgNode::Symbol:
- case QSvgNode::Marker:
- case QSvgNode::Pattern:
- {
+ }
+ } else {
+ switch (m_nodes.top()->type()) {
+ case QSvgNode::Doc:
+ case QSvgNode::Group:
+ case QSvgNode::Defs:
+ case QSvgNode::Switch:
+ case QSvgNode::Mask:
+ case QSvgNode::Symbol:
+ case QSvgNode::Marker:
+ case QSvgNode::Pattern:
+ {
+ node = method(m_nodes.top(), attributes, this);
+ if (node) {
QSvgStructureNode *group =
static_cast<QSvgStructureNode*>(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;
- }
}
+ 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());
+ break;
+ }
+ }
- if (node) {
- parseCoreNode(node, attributes);
+ if (node) {
+ parseCoreNode(node, attributes);
#ifndef QT_NO_CSSPARSER
- cssStyleLookup(node, this, m_selector);
+ cssStyleLookup(node, this, m_selector);
#endif
- parseStyle(node, attributes, this);
- if (node->type() == QSvgNode::Filter)
- m_toBeResolved.append(node);
- }
+ parseStyle(node, attributes, this);
+ if (node->type() == QSvgNode::Filter)
+ m_toBeResolved.append(node);
}
} else if (FactoryMethod method = findGraphicsFactory(localName, options())) {
//rendering element
diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
index 168dd0e..5d64b04 100644
--- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
+++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
@@ -80,6 +80,7 @@ private slots:
void testSymbol();
void testMarker();
void testPatternElement();
+ void testMisplacedElement();
void testCycles();
void testFeFlood();
void testFeOffset();
@@ -2109,6 +2110,31 @@ void tst_QSvgRenderer::testPatternElement()
QCOMPARE(refImage, image);
}
+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 <pattern> element is misplaced in the <text> 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"(<svg>
+ <text><pattern id="ptn" width="4" height="4"/></text>
+ <g fill="url(#ptn) "/>
+ </svg>)");
+
+ QImage image(20, 20, QImage::Format_ARGB32_Premultiplied);
+ image.fill(Qt::green);
+ QImage refImage = image.copy();
+
+ QTest::ignoreMessage(QtWarningMsg, "<input>:2:68: Could not add child element to parent "
+ "element because the types are incorrect.");
+ QTest::ignoreMessage(QtWarningMsg, "<input>:4:28: Could not resolve property: #ptn");
+
+ QSvgRenderer renderer(svg);
+ QPainter painter(&image);
+ renderer.render(&painter);
+ QCOMPARE(image, refImage);
+}
+
void tst_QSvgRenderer::testCycles()
{
QByteArray svgDoc(R"(<svg viewBox="0 0 200 200">
--
2.47.3

107
RHEL-119719.patch Normal file
View File

@ -0,0 +1,107 @@
From bacbd251c26f38bb59446c938b7bb3f3fa1c7db2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Robert=20L=C3=B6hning?= <robert.loehning@qt.io>
Date: Wed, 18 Jun 2025 16:02:32 +0200
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.10 6.9 6.8
Change-Id: If011c15fde50dcefeb653d1d5995ff1347e7b5ac
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
---
src/svg/qsvghandler.cpp | 4 +---
src/svg/qsvgstructure.cpp | 8 ++++++++
src/svg/qsvgstructure_p.h | 1 +
tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 3 +++
4 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index 2bd14c81..4383e87a 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -4646,9 +4646,7 @@ 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.
- if (remainingUnfinishedElements
- && startElement(xml->name().toString(), xml->attributes())
- && !detectCyclesAndWarn(m_doc)) {
+ if (remainingUnfinishedElements && startElement(xml->name().toString(), xml->attributes())) {
--remainingUnfinishedElements;
} else {
delete m_doc;
diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp
index e08f1bc1..d073b1c4 100644
--- a/src/svg/qsvgstructure.cpp
+++ b/src/svg/qsvgstructure.cpp
@@ -800,6 +800,7 @@ QSvgPattern::QSvgPattern(QSvgNode *parent, QSvgRectF bounds, QRectF viewBox,
m_rect(bounds),
m_viewBox(viewBox),
m_contentUnits(contentUnits),
+ m_isRendering(false),
m_transform(transform)
{
@@ -885,6 +886,13 @@ QImage QSvgPattern::renderPattern(QSize size, qreal contentScaleX, qreal content
}
pattern.fill(Qt::transparent);
+ if (m_isRendering) {
+ qCWarning(lcSvgDraw) << "The pattern is trying to render itself recursively. "
+ "Returning a transparent QImage of the right size.";
+ return pattern;
+ }
+ QScopedValueRollback<bool> guard(m_isRendering, true);
+
// Draw the pattern using our QPainter.
QPainter patternPainter(&pattern);
QSvgExtraStates patternStates;
diff --git a/src/svg/qsvgstructure_p.h b/src/svg/qsvgstructure_p.h
index 63a83964..f95508f4 100644
--- a/src/svg/qsvgstructure_p.h
+++ b/src/svg/qsvgstructure_p.h
@@ -241,6 +241,7 @@ private:
QSvgRectF m_rect;
QRectF m_viewBox;
QtSvg::UnitTypes m_contentUnits;
+ mutable bool m_isRendering;
QTransform m_transform;
};
diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
index 5d64b04f..894af4f9 100644
--- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
+++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
@@ -1805,6 +1805,9 @@ void tst_QSvgRenderer::ossFuzzLoad_data()
// resulted in stack overflow
QTest::newRow("cyclic-reference") // id=42532991
<< R"-(<svg><pattern height="3" width="9" id="c"><path d="v4T1-" stroke="url(#c)"><symbol>)-"_ba;
+ // resulted in stack overflow
+ QTest::newRow("cyclic-reference-from-parent") // id=390467765
+ << R"-(<svg stroke="url(#c)"><pattern height="2" width="4" id="c"/><path stroke="#F00" d="v2"/></svg>)-"_ba;
}
void tst_QSvgRenderer::ossFuzzLoad()
--
2.47.3

View File

@ -1,6 +0,0 @@
--- !Policy
product_versions:
- rhel-10
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: desktop-qe.desktop-ci.tier1-gating.functional}

View File

@ -12,7 +12,7 @@
Summary: Qt6 - Support for rendering and displaying SVG
Name: qt6-%{qt_module}
Version: 6.9.1
Release: 2%{?dist}
Release: 2%{?dist}.2
License: LGPL-3.0-only OR GPL-3.0-only WITH Qt-GPL-exception-1.0
Url: http://www.qt.io
@ -27,6 +27,9 @@ Source0: https://download.qt.io/official_releases/qt/%{majmin}/%{version}/submod
# Upstream patches
Patch50: qtsvg-dont-add-outlines-to-text-when-there-is-none.patch
Patch51: RHEL-119699.patch
# https://github.com/qt/qtsvg/commit/9e5bed9584ab65d56cd5fbac0471e06e37a54412
Patch52: RHEL-119719.patch
# filter plugin provides
%global __provides_exclude_from ^%{_qt6_plugindir}/.*\\.so$
@ -147,6 +150,15 @@ popd
%endif
%changelog
* Tue Nov 11 2025 RHEL Packaging Agent <jotnar@redhat.com> - 6.9.1-2.2
- Fix CVE-2025-10728: Replace quadratic cycle check with linear recursion
guard to prevent stack overflow
Resolves: RHEL-119719
* Wed Oct 29 2025 RHEL Packaging Agent <jotnar@redhat.com> - 6.9.1-2.1
- Fix CVE-2025-10729: Prevent dangling pointers in SVG group node creation
Resolves: RHEL-119699
* Mon Jun 23 2025 Jan Grulich <jgrulich@redhat.com> - 6.9.1-2
- Upstream backport: Don't add outlines to text when there is none
Resolves: RHEL-78552

View File

@ -1,7 +0,0 @@
---
ignore:
- '/usr/lib*/qt6/tests/*'
annocheck:
ignore:
- '/usr/lib*/qt6/examples/*'