[neon/qt/qtsvg/Neon/release] debian: Backport upstream commit to do stricter error checking when parsing path nodes.

Dmitry Shachnev null at kde.org
Thu May 5 13:13:22 BST 2022


Git commit 1bb81f2ef378aa822e7efd9d4218d9a246940b8d by Dmitry Shachnev.
Committed on 07/01/2022 at 19:44.
Pushed by jriddell into branch 'Neon/release'.

Backport upstream commit to do stricter error checking when parsing path nodes.

Closes: #1002991.

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

https://invent.kde.org/neon/qt/qtsvg/commit/1bb81f2ef378aa822e7efd9d4218d9a246940b8d

diff --git a/debian/changelog b/debian/changelog
index 45869fc..13b2b86 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,8 @@
 qtsvg-opensource-src (5.15.2-4) UNRELEASED; urgency=medium
 
+  [ Dmitry Shachnev ]
+  * Backport upstream commit to do stricter error checking when parsing path
+    nodes (CVE-2021-45930, closes: #1002991).
 
  -- Debian Qt/KDE Maintainers <debian-qt-kde at lists.debian.org>  Fri, 07 Jan 2022 22:42:55 +0300
 
diff --git a/debian/patches/CVE-2021-45930.diff b/debian/patches/CVE-2021-45930.diff
new file mode 100644
index 0000000..deae622
--- /dev/null
+++ b/debian/patches/CVE-2021-45930.diff
@@ -0,0 +1,204 @@
+Description: do stricter error checking when parsing path nodes
+ The SVG spec mandates that path parsing should terminate on the first
+ error encountered, and an error be reported. To improve the handling
+ of corrupt files, implement such error handling, and also limit the
+ number of QPainterPath elements to a reasonable range.
+Origin: upstream, https://code.qt.io/cgit/qt/qtsvg.git/commit/?id=36cfd9efb9b22b89
+Last-Update: 2022-01-07
+
+--- a/src/svg/qsvghandler.cpp
++++ b/src/svg/qsvghandler.cpp
+@@ -1615,6 +1615,7 @@ static void pathArc(QPainterPath &path,
+ 
+ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
+ {
++    const int maxElementCount = 0x7fff; // Assume file corruption if more path elements than this
+     qreal x0 = 0, y0 = 0;              // starting point
+     qreal x = 0, y = 0;                // current point
+     char lastMode = 0;
+@@ -1622,7 +1623,8 @@ static bool parsePathDataFast(const QStr
+     const QChar *str = dataStr.constData();
+     const QChar *end = str + dataStr.size();
+ 
+-    while (str != end) {
++    bool ok = true;
++    while (ok && str != end) {
+         while (str->isSpace() && (str + 1) != end)
+             ++str;
+         QChar pathElem = *str;
+@@ -1636,14 +1638,13 @@ static bool parsePathDataFast(const QStr
+             arg.append(0);//dummy
+         const qreal *num = arg.constData();
+         int count = arg.count();
+-        while (count > 0) {
++        while (ok && count > 0) {
+             qreal offsetX = x;        // correction offsets
+             qreal offsetY = y;        // for relative commands
+             switch (pathElem.unicode()) {
+             case 'm': {
+                 if (count < 2) {
+-                    num++;
+-                    count--;
++                    ok = false;
+                     break;
+                 }
+                 x = x0 = num[0] + offsetX;
+@@ -1660,8 +1661,7 @@ static bool parsePathDataFast(const QStr
+                 break;
+             case 'M': {
+                 if (count < 2) {
+-                    num++;
+-                    count--;
++                    ok = false;
+                     break;
+                 }
+                 x = x0 = num[0];
+@@ -1687,8 +1687,7 @@ static bool parsePathDataFast(const QStr
+                 break;
+             case 'l': {
+                 if (count < 2) {
+-                    num++;
+-                    count--;
++                    ok = false;
+                     break;
+                 }
+                 x = num[0] + offsetX;
+@@ -1701,8 +1700,7 @@ static bool parsePathDataFast(const QStr
+                 break;
+             case 'L': {
+                 if (count < 2) {
+-                    num++;
+-                    count--;
++                    ok = false;
+                     break;
+                 }
+                 x = num[0];
+@@ -1742,8 +1740,7 @@ static bool parsePathDataFast(const QStr
+                 break;
+             case 'c': {
+                 if (count < 6) {
+-                    num += count;
+-                    count = 0;
++                    ok = false;
+                     break;
+                 }
+                 QPointF c1(num[0] + offsetX, num[1] + offsetY);
+@@ -1759,8 +1756,7 @@ static bool parsePathDataFast(const QStr
+             }
+             case 'C': {
+                 if (count < 6) {
+-                    num += count;
+-                    count = 0;
++                    ok = false;
+                     break;
+                 }
+                 QPointF c1(num[0], num[1]);
+@@ -1776,8 +1772,7 @@ static bool parsePathDataFast(const QStr
+             }
+             case 's': {
+                 if (count < 4) {
+-                    num += count;
+-                    count = 0;
++                    ok = false;
+                     break;
+                 }
+                 QPointF c1;
+@@ -1798,8 +1793,7 @@ static bool parsePathDataFast(const QStr
+             }
+             case 'S': {
+                 if (count < 4) {
+-                    num += count;
+-                    count = 0;
++                    ok = false;
+                     break;
+                 }
+                 QPointF c1;
+@@ -1820,8 +1814,7 @@ static bool parsePathDataFast(const QStr
+             }
+             case 'q': {
+                 if (count < 4) {
+-                    num += count;
+-                    count = 0;
++                    ok = false;
+                     break;
+                 }
+                 QPointF c(num[0] + offsetX, num[1] + offsetY);
+@@ -1836,8 +1829,7 @@ static bool parsePathDataFast(const QStr
+             }
+             case 'Q': {
+                 if (count < 4) {
+-                    num += count;
+-                    count = 0;
++                    ok = false;
+                     break;
+                 }
+                 QPointF c(num[0], num[1]);
+@@ -1852,8 +1844,7 @@ static bool parsePathDataFast(const QStr
+             }
+             case 't': {
+                 if (count < 2) {
+-                    num += count;
+-                    count = 0;
++                    ok = false;
+                     break;
+                 }
+                 QPointF e(num[0] + offsetX, num[1] + offsetY);
+@@ -1873,8 +1864,7 @@ static bool parsePathDataFast(const QStr
+             }
+             case 'T': {
+                 if (count < 2) {
+-                    num += count;
+-                    count = 0;
++                    ok = false;
+                     break;
+                 }
+                 QPointF e(num[0], num[1]);
+@@ -1894,8 +1884,7 @@ static bool parsePathDataFast(const QStr
+             }
+             case 'a': {
+                 if (count < 7) {
+-                    num += count;
+-                    count = 0;
++                    ok = false;
+                     break;
+                 }
+                 qreal rx = (*num++);
+@@ -1917,8 +1906,7 @@ static bool parsePathDataFast(const QStr
+                 break;
+             case 'A': {
+                 if (count < 7) {
+-                    num += count;
+-                    count = 0;
++                    ok = false;
+                     break;
+                 }
+                 qreal rx = (*num++);
+@@ -1939,12 +1927,15 @@ static bool parsePathDataFast(const QStr
+             }
+                 break;
+             default:
+-                return false;
++                ok = false;
++                break;
+             }
+             lastMode = pathElem.toLatin1();
++            if (path.elementCount() > maxElementCount)
++                ok = false;
+         }
+     }
+-    return true;
++    return ok;
+ }
+ 
+ static bool parseStyle(QSvgNode *node,
+@@ -2980,8 +2971,8 @@ static QSvgNode *createPathNode(QSvgNode
+ 
+     QPainterPath qpath;
+     qpath.setFillRule(Qt::WindingFill);
+-    //XXX do error handling
+-    parsePathDataFast(data, qpath);
++    if (!parsePathDataFast(data, qpath))
++        qCWarning(lcSvgHandler, "Invalid path data; path truncated.");
+ 
+     QSvgNode *path = new QSvgPath(parent, qpath);
+     return path;
diff --git a/debian/patches/series b/debian/patches/series
index b54f1fe..3621503 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,2 @@
 CVE-2021-3481.diff
+CVE-2021-45930.diff



More information about the Neon-commits mailing list