qt5-qtsvg/CVE-2021-45930.patch

222 lines
7.4 KiB
Diff
Raw Normal View History

2022-01-18 09:38:08 +08:00
From 36cfd9efb9b22b891adee9c48d30202289cfa620 Mon Sep 17 00:00:00 2001
2022-01-14 10:09:41 +08:00
From: Eirik Aavitsland <eirik.aavitsland@qt.io>
Date: Mon, 25 Oct 2021 14:17:55 +0200
Subject: [PATCH] Do stricter error checking when parsing path nodes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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.
Fixes: QTBUG-96044
2022-01-18 09:38:08 +08:00
Pick-to: 6.2 5.15 5.12
2022-01-14 10:09:41 +08:00
Change-Id: Ic5e65d6b658516d6f1317c72de365c8c7ad81891
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Reviewed-by: Robert Löhning <robert.loehning@qt.io>
---
src/svg/qsvghandler.cpp | 59 +++++++++++++++++------------------------
1 file changed, 25 insertions(+), 34 deletions(-)
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
2022-01-18 09:38:08 +08:00
index db29211..dd869ff 100644
2022-01-14 10:09:41 +08:00
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
2022-01-18 09:38:08 +08:00
@@ -1615,6 +1615,7 @@ static void pathArc(QPainterPath &path,
2022-01-14 10:09:41 +08:00
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;
2022-01-18 09:38:08 +08:00
@@ -1622,7 +1623,8 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
const QChar *str = dataStr.constData();
const QChar *end = str + dataStr.size();
- while (str != end) {
+ bool ok = true;
+ while (ok && str != end) {
2022-01-18 09:38:08 +08:00
while (str->isSpace() && (str + 1) != end)
2022-01-14 10:09:41 +08:00
++str;
QChar pathElem = *str;
2022-01-18 09:38:08 +08:00
@@ -1636,14 +1638,13 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
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;
2022-01-18 09:38:08 +08:00
@@ -1660,8 +1661,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
break;
case 'M': {
if (count < 2) {
- num++;
- count--;
+ ok = false;
break;
}
x = x0 = num[0];
2022-01-18 09:38:08 +08:00
@@ -1687,8 +1687,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
break;
case 'l': {
if (count < 2) {
- num++;
- count--;
+ ok = false;
break;
}
x = num[0] + offsetX;
2022-01-18 09:38:08 +08:00
@@ -1701,8 +1700,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
break;
case 'L': {
if (count < 2) {
- num++;
- count--;
+ ok = false;
break;
}
x = num[0];
2022-01-18 09:38:08 +08:00
@@ -1742,8 +1740,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
break;
case 'c': {
if (count < 6) {
- num += count;
- count = 0;
+ ok = false;
break;
}
QPointF c1(num[0] + offsetX, num[1] + offsetY);
2022-01-18 09:38:08 +08:00
@@ -1759,8 +1756,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
}
case 'C': {
if (count < 6) {
- num += count;
- count = 0;
+ ok = false;
break;
}
QPointF c1(num[0], num[1]);
2022-01-18 09:38:08 +08:00
@@ -1776,8 +1772,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
}
case 's': {
if (count < 4) {
- num += count;
- count = 0;
+ ok = false;
break;
}
QPointF c1;
2022-01-18 09:38:08 +08:00
@@ -1798,8 +1793,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
}
case 'S': {
if (count < 4) {
- num += count;
- count = 0;
+ ok = false;
break;
}
QPointF c1;
2022-01-18 09:38:08 +08:00
@@ -1820,8 +1814,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
}
case 'q': {
if (count < 4) {
- num += count;
- count = 0;
+ ok = false;
break;
}
QPointF c(num[0] + offsetX, num[1] + offsetY);
2022-01-18 09:38:08 +08:00
@@ -1836,8 +1829,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
}
case 'Q': {
if (count < 4) {
- num += count;
- count = 0;
+ ok = false;
break;
}
QPointF c(num[0], num[1]);
2022-01-18 09:38:08 +08:00
@@ -1852,8 +1844,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
}
case 't': {
if (count < 2) {
- num += count;
- count = 0;
+ ok = false;
break;
}
QPointF e(num[0] + offsetX, num[1] + offsetY);
2022-01-18 09:38:08 +08:00
@@ -1873,8 +1864,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
}
case 'T': {
if (count < 2) {
- num += count;
- count = 0;
+ ok = false;
break;
}
QPointF e(num[0], num[1]);
2022-01-18 09:38:08 +08:00
@@ -1894,8 +1884,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
}
case 'a': {
if (count < 7) {
- num += count;
- count = 0;
+ ok = false;
break;
}
qreal rx = (*num++);
2022-01-18 09:38:08 +08:00
@@ -1917,8 +1906,7 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
break;
case 'A': {
if (count < 7) {
- num += count;
- count = 0;
+ ok = false;
break;
}
qreal rx = (*num++);
2022-01-18 09:38:08 +08:00
@@ -1939,12 +1927,15 @@ static bool parsePathDataFast(const QStr
2022-01-14 10:09:41 +08:00
}
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,
2022-01-18 09:38:08 +08:00
@@ -2980,8 +2971,8 @@ static QSvgNode *createPathNode(QSvgNode
2022-01-14 10:09:41 +08:00
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;