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
9 changed files with 317 additions and 55 deletions

32
.gitignore vendored
View File

@ -1,31 +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.10.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

@ -11,8 +11,8 @@
Summary: Qt6 - Support for rendering and displaying SVG
Name: qt6-%{qt_module}
Version: 6.10.1
Release: 1%{?dist}
Version: 6.9.1
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
@ -26,7 +26,10 @@ Source0: https://download.qt.io/official_releases/qt/%{majmin}/%{version}/submod
%endif
# 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$
@ -127,16 +130,18 @@ popd
%dir %{_qt6_libdir}/cmake/Qt6Svg/
%dir %{_qt6_libdir}/cmake/Qt6SvgPrivate/
%dir %{_qt6_libdir}/cmake/Qt6SvgWidgets/
%dir %{_qt6_libdir}/cmake/Qt6SvgWidgetsPrivate/
%{_qt6_libdir}/cmake/Qt6Svg/*.cmake
%{_qt6_libdir}/cmake/Qt6SvgPrivate/*cmake
%{_qt6_libdir}/cmake/Qt6SvgWidgets/*.cmake
%{_qt6_libdir}/cmake/Qt6SvgWidgetsPrivate/*.cmake
%{_qt6_libdir}/qt6/metatypes/qt6*_metatypes.json
%{_qt6_libdir}/qt6/modules/*.json
%{_qt6_libdir}/pkgconfig/*.pc
%if 0%{?examples}
# FIXME there don't seem to be any examples
%files examples
%{_qt6_examplesdir}/
%endif
%if 0%{?build_tests}
@ -145,9 +150,14 @@ popd
%endif
%changelog
* Mon Nov 24 2025 Jan Grulich <jgrulich@redhat.com> - 6.10.1-1
- 6.10.1
Resolves: RHEL-109197
* 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

View File

@ -0,0 +1,39 @@
From 07b3434f91c95d196f687c51e1a58a95a0b1ef2e Mon Sep 17 00:00:00 2001
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Date: Wed, 28 May 2025 09:47:49 +0200
Subject: [PATCH] Don't add outlines to text when there is none
Qt SVG would indiscriminately add outlines to text. Since the pen
has Qt::NoBrush, the outline would not be visible with a normal
QPainter, but it did always trigger the QPainterPath code path which
is taken when the text uses features we don't support through the
native rasterizer backend.
In turn, this would cause all text to be unsearchable when printing
the SVG to a PDF. In addition, all text would be too thick in this
case because the PDF generator adds the outline even if the brush
is Qt::NoBrush.
Pick-to: 6.8
Fixes: QTBUG-123817
Change-Id: Icff637e65ea9f0c867a374fcbba3f6ad4a6756fc
Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
(cherry picked from commit 4d9bd9572f340fb9bc2f96f55ea6836386ac0b0d)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 09918e3da44f80bff8bb13cd65984bd7e00c95e6)
---
diff --git a/src/svg/qsvggraphics.cpp b/src/svg/qsvggraphics.cpp
index 67879da..7d6fca9 100644
--- a/src/svg/qsvggraphics.cpp
+++ b/src/svg/qsvggraphics.cpp
@@ -446,7 +446,8 @@
range.start = paragraphs.back().size();
range.length = newText.size();
range.format.setFont(font);
- range.format.setTextOutline(p->pen());
+ if (p->pen().style() != Qt::NoPen && p->pen().brush() != Qt::NoBrush)
+ range.format.setTextOutline(p->pen());
range.format.setForeground(p->brush());
if (appendSpace) {

View File

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

View File

@ -1 +1 @@
SHA512 (qtsvg-everywhere-src-6.10.1.tar.xz) = 26d061a24e7196edf07c508ae12bf2d2f1f99cdb9a99ab993aefd0b9d135a6da00eef805f00cbdf022f7b3255f378bc491be1534f3837858078285d543bbe2c7
SHA512 (qtsvg-everywhere-src-6.9.1.tar.xz) = d36fe4921fb9d7968378e0e1f7131574642baba7eec9a492283c039fec64e307f0a4148bd7fed83ce7b3d92a1af3d9cb31917ced0f15a186262de8bb7fdc615e