[neon/qt/qtbase/Neon/release] debian: Fix massive memory consumption when rendering specially crafted SVG files.

Dmitry Shachnev null at kde.org
Thu May 5 10:59:25 BST 2022


Git commit 06bc2544d19a7c8a5440f31994cab2cbc8f88d7a by Dmitry Shachnev.
Committed on 27/11/2021 at 18:12.
Pushed by jriddell into branch 'Neon/release'.

Fix massive memory consumption when rendering specially crafted SVG files.

This fixes CVE-2021-38593.
LP: #1950193.

M  +3    -0    debian/changelog
A  +84   -0    debian/patches/CVE-2021-38593.diff
M  +1    -0    debian/patches/series

https://invent.kde.org/neon/qt/qtbase/commit/06bc2544d19a7c8a5440f31994cab2cbc8f88d7a

diff --git a/debian/changelog b/debian/changelog
index 7c6c031..7dbdc27 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,8 @@
 qtbase-opensource-src (5.15.2+dfsg-14) UNRELEASED; urgency=medium
 
+  [ Dmitry Shachnev ]
+  * Backport four upstream commits to fix massive memory consumption when
+    rendering specially crafted SVG files (CVE-2021-38593, LP: #1950193).
 
  -- Debian Qt/KDE Maintainers <debian-qt-kde at lists.debian.org>  Sat, 27 Nov 2021 21:06:09 +0300
 
diff --git a/debian/patches/CVE-2021-38593.diff b/debian/patches/CVE-2021-38593.diff
new file mode 100644
index 0000000..b659fc8
--- /dev/null
+++ b/debian/patches/CVE-2021-38593.diff
@@ -0,0 +1,84 @@
+Description: avoid processing-intensive painting of high number of tiny dashes
+ When stroking a dashed path, an unnecessary amount of processing would
+ be spent if there is a huge number of dashes visible, e.g. because of
+ scaling. Since the dashes are too small to be individually visible
+ anyway, just replace with a semi-transparent solid line for such
+ cases.
+Origin: upstream, commits:
+ https://code.qt.io/cgit/qt/qtbase.git/commit/?id=f4d791b330d02777
+ https://code.qt.io/cgit/qt/qtbase.git/commit/?id=6b400e3147dcfd8c
+ https://code.qt.io/cgit/qt/qtbase.git/commit/?id=84aba80944a2e1c3
+ https://code.qt.io/cgit/qt/qtbase.git/commit/?id=81a7344e1dea5622
+Last-Update: 2021-11-27
+
+--- a/src/gui/painting/qpaintengineex.cpp
++++ b/src/gui/painting/qpaintengineex.cpp
+@@ -385,10 +385,10 @@ QPainterState *QPaintEngineEx::createSta
+ 
+ Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
+ 
+-void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
++void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen)
+ {
+ #ifdef QT_DEBUG_DRAW
+-    qDebug() << "QPaintEngineEx::stroke()" << pen;
++    qDebug() << "QPaintEngineEx::stroke()" << inPen;
+ #endif
+ 
+     Q_D(QPaintEngineEx);
+@@ -403,6 +403,38 @@ void QPaintEngineEx::stroke(const QVecto
+         d->stroker.setCubicToHook(qpaintengineex_cubicTo);
+     }
+ 
++    QRectF clipRect;
++    QPen pen = inPen;
++    if (pen.style() > Qt::SolidLine) {
++        QRectF cpRect = path.controlPointRect();
++        const QTransform &xf = state()->matrix;
++        if (qt_pen_is_cosmetic(pen, state()->renderHints)) {
++            clipRect = d->exDeviceRect;
++            cpRect.translate(xf.dx(), xf.dy());
++        } else {
++            clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect));
++        }
++        // Check to avoid generating unwieldy amount of dashes that will not be visible anyway
++        qreal pw = pen.widthF() ? pen.widthF() : 1;
++        QRectF extentRect = cpRect.adjusted(-pw, -pw, pw, pw) & clipRect;
++        qreal extent = qMax(extentRect.width(), extentRect.height());
++        qreal patternLength = 0;
++        const QVector<qreal> pattern = pen.dashPattern();
++        const int patternSize = qMin(pattern.size(), 32);
++        for (int i = 0; i < patternSize; i++)
++            patternLength += qMax(pattern.at(i), qreal(0));
++        patternLength *= pw;
++        if (qFuzzyIsNull(patternLength)) {
++            pen.setStyle(Qt::NoPen);
++        } else if (extent / patternLength > 10000) {
++            // approximate stream of tiny dashes with semi-transparent solid line
++            pen.setStyle(Qt::SolidLine);
++            QColor color(pen.color());
++            color.setAlpha(color.alpha() / 2);
++            pen.setColor(color);
++        }
++    }
++
+     if (!qpen_fast_equals(pen, d->strokerPen)) {
+         d->strokerPen = pen;
+         d->stroker.setJoinStyle(pen.joinStyle());
+@@ -430,14 +462,8 @@ void QPaintEngineEx::stroke(const QVecto
+         return;
+     }
+ 
+-    if (pen.style() > Qt::SolidLine) {
+-        if (qt_pen_is_cosmetic(pen, state()->renderHints)){
+-            d->activeStroker->setClipRect(d->exDeviceRect);
+-        } else {
+-            QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect));
+-            d->activeStroker->setClipRect(clipRect);
+-        }
+-    }
++    if (!clipRect.isNull())
++        d->activeStroker->setClipRect(clipRect);
+ 
+     if (d->activeStroker == &d->stroker)
+         d->stroker.setForceOpen(path.hasExplicitOpen());
diff --git a/debian/patches/series b/debian/patches/series
index 20e561f..8c127ef 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -13,6 +13,7 @@ full_width_selection_rtl.diff
 xcb_add_a_timeout_control_when_reading_INCR_property.diff
 fix_recursion_crash.diff
 mysql_field_readonly.diff
+CVE-2021-38593.diff
 
 # Debian specific.
 gnukfreebsd.diff



More information about the Neon-commits mailing list