[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