Skip to content

Commit efe620c

Browse files
PawelWMSSumynwa
andauthored
Patched CVE-2021-38593 in qt5-qtbase. (#7907)
Co-authored-by: Sumynwa <sumedh.alok@gmail.com>
1 parent 1cdb253 commit efe620c

2 files changed

Lines changed: 302 additions & 1 deletion

File tree

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
From 7f345f2a1c8d9f60c60e8a9d8cc90729794bd2f1 Mon Sep 17 00:00:00 2001
2+
From: Eirik Aavitsland <eirik.aavitsland@qt.io>
3+
Date: Tue, 13 Apr 2021 14:23:45 +0200
4+
Subject: Avoid processing-intensive painting of high number of tiny dashes
5+
6+
When stroking a dashed path, an unnecessary amount of processing would
7+
be spent if there is a huge number of dashes visible, e.g. because of
8+
scaling. Since the dashes are too small to be indivdually visible
9+
anyway, just replace with a semi-transparent solid line for such
10+
cases.
11+
12+
Change-Id: I9e9f7861257ad5bce46a0cf113d1a9d7824911e6
13+
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
14+
(cherry picked from commit f4d791b330d02777fcaf02938732892eb3167e9b)
15+
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
16+
---
17+
src/gui/painting/qpaintengineex.cpp | 44 +++++++++++++++++++-----
18+
tests/auto/other/lancelot/scripts/tinydashes.qps | 34 ++++++++++++++++++
19+
2 files changed, 69 insertions(+), 9 deletions(-)
20+
create mode 100644 tests/auto/other/lancelot/scripts/tinydashes.qps
21+
22+
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
23+
index f4cbf15fc7..f04e3a498d 100644
24+
--- a/src/gui/painting/qpaintengineex.cpp
25+
+++ b/src/gui/painting/qpaintengineex.cpp
26+
@@ -385,7 +385,7 @@ QPainterState *QPaintEngineEx::createState(QPainterState *orig) const
27+
28+
Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
29+
30+
-void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
31+
+void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen)
32+
{
33+
#ifdef QT_DEBUG_DRAW
34+
qDebug() << "QPaintEngineEx::stroke()" << pen;
35+
@@ -403,6 +403,38 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
36+
d->stroker.setCubicToHook(qpaintengineex_cubicTo);
37+
}
38+
39+
+ QRectF clipRect;
40+
+ QPen pen = inPen;
41+
+ if (pen.style() > Qt::SolidLine) {
42+
+ QRectF cpRect = path.controlPointRect();
43+
+ const QTransform &xf = state()->matrix;
44+
+ if (qt_pen_is_cosmetic(pen, state()->renderHints)) {
45+
+ clipRect = d->exDeviceRect;
46+
+ cpRect.translate(xf.dx(), xf.dy());
47+
+ } else {
48+
+ clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect));
49+
+ }
50+
+ // Check to avoid generating unwieldy amount of dashes that will not be visible anyway
51+
+ QRectF extentRect = cpRect & clipRect;
52+
+ qreal extent = qMax(extentRect.width(), extentRect.height());
53+
+ qreal patternLength = 0;
54+
+ const QVector<qreal> pattern = pen.dashPattern();
55+
+ const int patternSize = qMin(pattern.size(), 32);
56+
+ for (int i = 0; i < patternSize; i++)
57+
+ patternLength += qMax(pattern.at(i), qreal(0));
58+
+ if (pen.widthF())
59+
+ patternLength *= pen.widthF();
60+
+ if (qFuzzyIsNull(patternLength)) {
61+
+ pen.setStyle(Qt::NoPen);
62+
+ } else if (extent / patternLength > 10000) {
63+
+ // approximate stream of tiny dashes with semi-transparent solid line
64+
+ pen.setStyle(Qt::SolidLine);
65+
+ QColor color(pen.color());
66+
+ color.setAlpha(color.alpha() / 2);
67+
+ pen.setColor(color);
68+
+ }
69+
+ }
70+
+
71+
if (!qpen_fast_equals(pen, d->strokerPen)) {
72+
d->strokerPen = pen;
73+
d->stroker.setJoinStyle(pen.joinStyle());
74+
@@ -430,14 +462,8 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
75+
return;
76+
}
77+
78+
- if (pen.style() > Qt::SolidLine) {
79+
- if (qt_pen_is_cosmetic(pen, state()->renderHints)){
80+
- d->activeStroker->setClipRect(d->exDeviceRect);
81+
- } else {
82+
- QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect));
83+
- d->activeStroker->setClipRect(clipRect);
84+
- }
85+
- }
86+
+ if (!clipRect.isNull())
87+
+ d->activeStroker->setClipRect(clipRect);
88+
89+
const QPainterPath::ElementType *types = path.elements();
90+
const qreal *points = path.points();
91+
diff --git a/tests/auto/other/lancelot/scripts/tinydashes.qps b/tests/auto/other/lancelot/scripts/tinydashes.qps
92+
new file mode 100644
93+
index 0000000000..d41ced7f5f
94+
--- /dev/null
95+
+++ b/tests/auto/other/lancelot/scripts/tinydashes.qps
96+
@@ -0,0 +1,34 @@
97+
+# Version: 1
98+
+# CheckVsReference: 5%
99+
+
100+
+path_addEllipse mypath 20.0 20.0 200.0 200.0
101+
+
102+
+save
103+
+setPen blue 20 SolidLine FlatCap
104+
+pen_setCosmetic true
105+
+pen_setDashPattern [ 0.0004 0.0004 ]
106+
+setBrush yellow
107+
+
108+
+drawPath mypath
109+
+translate 300 0
110+
+setRenderHint Antialiasing true
111+
+drawPath mypath
112+
+restore
113+
+
114+
+path_addEllipse bigpath 200000.0 200000.0 2000000.0 2000000.0
115+
+
116+
+setPen blue 20 DotLine FlatCap
117+
+setBrush yellow
118+
+
119+
+save
120+
+translate 0 300
121+
+scale 0.0001 0.00011
122+
+drawPath bigpath
123+
+restore
124+
+
125+
+save
126+
+translate 300 300
127+
+setRenderHint Antialiasing true
128+
+scale 0.0001 0.00011
129+
+drawPath bigpath
130+
+restore
131+
--
132+
From 9378ba2ae857df7e21a384e514650823db2355c3 Mon Sep 17 00:00:00 2001
133+
From: Eirik Aavitsland <eirik.aavitsland@qt.io>
134+
Date: Fri, 23 Jul 2021 15:53:56 +0200
135+
Subject: Improve fix for avoiding huge number of tiny dashes
136+
MIME-Version: 1.0
137+
Content-Type: text/plain; charset=UTF-8
138+
Content-Transfer-Encoding: 8bit
139+
140+
Some pathological cases were not caught by the previous fix.
141+
142+
Fixes: QTBUG-95239
143+
Change-Id: I0337ee3923ff93ccb36c4d7b810a9c0667354cc5
144+
Reviewed-by: Robert Löhning <robert.loehning@qt.io>
145+
(cherry picked from commit 6b400e3147dcfd8cc3a393ace1bd118c93762e0c)
146+
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
147+
---
148+
src/gui/painting/qpaintengineex.cpp | 2 +-
149+
1 file changed, 1 insertion(+), 1 deletion(-)
150+
151+
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
152+
index f04e3a498d..bd6bdf7be1 100644
153+
--- a/src/gui/painting/qpaintengineex.cpp
154+
+++ b/src/gui/painting/qpaintengineex.cpp
155+
@@ -426,7 +426,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen)
156+
patternLength *= pen.widthF();
157+
if (qFuzzyIsNull(patternLength)) {
158+
pen.setStyle(Qt::NoPen);
159+
- } else if (extent / patternLength > 10000) {
160+
+ } else if (qFuzzyIsNull(extent) || extent / patternLength > 10000) {
161+
// approximate stream of tiny dashes with semi-transparent solid line
162+
pen.setStyle(Qt::SolidLine);
163+
QColor color(pen.color());
164+
--
165+
From 81998f50d039a6317a3130ace8d4ad304f9acbbf Mon Sep 17 00:00:00 2001
166+
From: Eirik Aavitsland <eirik.aavitsland@qt.io>
167+
Date: Fri, 30 Jul 2021 13:03:49 +0200
168+
Subject: Refix for avoiding huge number of tiny dashes
169+
170+
Previous fix hit too widely so some valid horizontal and vertical
171+
lines were affected; the root problem being that such lines have an
172+
empty control point rect (width or height is 0). Fix by caculating in
173+
the pen width.
174+
175+
Change-Id: I7a436e873f6d485028f6759d0e2c6456f07eebdc
176+
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
177+
(cherry picked from commit 84aba80944a2e1c3058d7a1372e0e66676411884)
178+
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
179+
---
180+
src/gui/painting/qpaintengineex.cpp | 8 +++---
181+
tests/auto/gui/painting/qpainter/tst_qpainter.cpp | 31 +++++++++++++++++++++++
182+
2 files changed, 35 insertions(+), 4 deletions(-)
183+
184+
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
185+
index bd6bdf7be1..d8223c1b3e 100644
186+
--- a/src/gui/painting/qpaintengineex.cpp
187+
+++ b/src/gui/painting/qpaintengineex.cpp
188+
@@ -415,18 +415,18 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen)
189+
clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect));
190+
}
191+
// Check to avoid generating unwieldy amount of dashes that will not be visible anyway
192+
- QRectF extentRect = cpRect & clipRect;
193+
+ qreal pw = pen.widthF() ? pen.widthF() : 1;
194+
+ QRectF extentRect = cpRect.adjusted(-pw, -pw, pw, pw) & clipRect;
195+
qreal extent = qMax(extentRect.width(), extentRect.height());
196+
qreal patternLength = 0;
197+
const QVector<qreal> pattern = pen.dashPattern();
198+
const int patternSize = qMin(pattern.size(), 32);
199+
for (int i = 0; i < patternSize; i++)
200+
patternLength += qMax(pattern.at(i), qreal(0));
201+
- if (pen.widthF())
202+
- patternLength *= pen.widthF();
203+
+ patternLength *= pw;
204+
if (qFuzzyIsNull(patternLength)) {
205+
pen.setStyle(Qt::NoPen);
206+
- } else if (qFuzzyIsNull(extent) || extent / patternLength > 10000) {
207+
+ } else if (extent / patternLength > 10000) {
208+
// approximate stream of tiny dashes with semi-transparent solid line
209+
pen.setStyle(Qt::SolidLine);
210+
QColor color(pen.color());
211+
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
212+
index bc0baed15c..697dcfa4a4 100644
213+
--- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
214+
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
215+
@@ -300,6 +300,7 @@ private slots:
216+
void fillPolygon();
217+
218+
void drawImageAtPointF();
219+
+ void scaledDashes();
220+
221+
private:
222+
void fillData();
223+
@@ -5308,6 +5309,36 @@ void tst_QPainter::drawImageAtPointF()
224+
paint.end();
225+
}
226+
227+
+void tst_QPainter::scaledDashes()
228+
+{
229+
+ // Test that we do not hit the limit-huge-number-of-dashes path
230+
+ QRgb fore = qRgb(0, 0, 0xff);
231+
+ QRgb back = qRgb(0xff, 0xff, 0);
232+
+ QImage image(5, 32, QImage::Format_RGB32);
233+
+ image.fill(back);
234+
+ QPainter p(&image);
235+
+ QPen pen(QColor(fore), 3, Qt::DotLine);
236+
+ p.setPen(pen);
237+
+ p.scale(1, 2);
238+
+ p.drawLine(2, 0, 2, 16);
239+
+ p.end();
240+
+
241+
+ bool foreFound = false;
242+
+ bool backFound = false;
243+
+ int i = 0;
244+
+ while (i < 32 && (!foreFound || !backFound)) {
245+
+ QRgb pix = image.pixel(3, i);
246+
+ if (pix == fore)
247+
+ foreFound = true;
248+
+ else if (pix == back)
249+
+ backFound = true;
250+
+ i++;
251+
+ }
252+
+
253+
+ QVERIFY(foreFound);
254+
+ QVERIFY(backFound);
255+
+}
256+
+
257+
QTEST_MAIN(tst_QPainter)
258+
259+
#include "tst_qpainter.moc"
260+
--
261+
From cca8ed0547405b1c018e995ad366ba0ab4c2a0e8 Mon Sep 17 00:00:00 2001
262+
From: Zhang Hao <zhanghao@uniontech.com>
263+
Date: Tue, 7 Sep 2021 14:50:22 +0800
264+
Subject: QPaintEngineEx: solve compile error
265+
266+
Use the same variable name in function
267+
Amends 6869d2463a2e0d71bd04dbc82f5d6ef4933dc510
268+
269+
Pick-to: 6.1 6.2
270+
Change-Id: If710a53993e84d048f9052f4fcf92eb57635f585
271+
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
272+
---
273+
src/gui/painting/qpaintengineex.cpp | 2 +-
274+
1 file changed, 1 insertion(+), 1 deletion(-)
275+
276+
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
277+
index 3577d71869..b6c0a9e1ff 100644
278+
--- a/src/gui/painting/qpaintengineex.cpp
279+
+++ b/src/gui/painting/qpaintengineex.cpp
280+
@@ -388,7 +388,7 @@ Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal
281+
void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen)
282+
{
283+
#ifdef QT_DEBUG_DRAW
284+
- qDebug() << "QPaintEngineEx::stroke()" << pen;
285+
+ qDebug() << "QPaintEngineEx::stroke()" << inPen;
286+
#endif
287+
288+
Q_D(QPaintEngineEx);
289+
--

SPECS/qt5-qtbase/qt5-qtbase.spec

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
Name: qt5-qtbase
3434
Summary: Qt5 - QtBase components
3535
Version: 5.12.11
36-
Release: 10%{?dist}
36+
Release: 11%{?dist}
3737
# See LICENSE.GPL3-EXCEPT.txt, for exception details
3838
License: GFDL AND LGPLv3 AND GPLv2 AND GPLv3 with exceptions AND QT License Agreement 4.0
3939
Vendor: Microsoft Corporation
@@ -148,6 +148,14 @@ Patch87: CVE-2023-38197.patch
148148
# Fix CVE-2023-51714
149149
Patch88: CVE-2023-51714.patch
150150

151+
# Fix taken from Ubuntu's backport: https://bugs.launchpad.net/ubuntu/+source/qtbase-opensource-src/+bug/1950193.
152+
# It's a combination of 4 commits:
153+
# - https://code.qt.io/cgit/qt/qtbase.git/commit/?id=9378ba2ae857df7e
154+
# - https://code.qt.io/cgit/qt/qtbase.git/commit/?id=81998f50d039a631
155+
# - https://code.qt.io/cgit/qt/qtbase.git/commit/?id=7f345f2a1c8d9f60
156+
# - https://code.qt.io/cgit/qt/qtbase.git/commit/?id=cca8ed0547405b1c
157+
Patch89: CVE-2021-38593.patch
158+
151159
# Do not check any files in %%{_qt5_plugindir}/platformthemes/ for requires.
152160
# Those themes are there for platform integration. If the required libraries are
153161
# not there, the platform to integrate with isn't either. Then Qt will just
@@ -257,6 +265,7 @@ Qt5 libraries used for drawing widgets and OpenGL items.
257265
%patch86 -p1
258266
%patch87 -p1
259267
%patch88 -p1
268+
%patch89 -p1
260269

261270
## upstream patches
262271

@@ -762,6 +771,9 @@ fi
762771
%{_qt5_libdir}/cmake/Qt5Gui/Qt5Gui_QXdgDesktopPortalThemePlugin.cmake
763772

764773
%changelog
774+
* Thu Feb 15 2024 Sumedh Sharma <sumsharma@microsoft.com> - 5.12.11-11
775+
- Add patch to resolve CVE-2021-38593, used Ubuntu's patch for guidance.
776+
765777
* Fri Jan 05 2024 Henry Beberman <henry.beberman@microsoft.com> - 5.12.11-10
766778
- Add patch to resolve CVE-2023-51714
767779

0 commit comments

Comments
 (0)