Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f7866e887 | |||
| a34ccaf034 |
31
.gitignore
vendored
31
.gitignore
vendored
@ -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
|
||||
|
||||
152
RHEL-119699.patch
Normal file
152
RHEL-119699.patch
Normal 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
107
RHEL-119719.patch
Normal 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
|
||||
|
||||
@ -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}
|
||||
@ -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
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
ignore:
|
||||
- '/usr/lib*/qt6/tests/*'
|
||||
annocheck:
|
||||
ignore:
|
||||
- '/usr/lib*/qt6/examples/*'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user