fix CVE-2015-9541

This commit is contained in:
jackie_wu 2020-09-21 20:38:29 +08:00
parent c183621eef
commit 9c17f843d8
2 changed files with 164 additions and 1 deletions

159
CVE-2015-9541.patch Normal file
View File

@ -0,0 +1,159 @@
From fd4be84d23a0db4186cb42e736a9de3af722c7f7 Mon Sep 17 00:00:00 2001
From: Lars Knoll <lars.knoll@qt.io>
Date: Wed, 26 Feb 2020 10:42:10 +0100
Subject: Add an expansion limit for entities
Recursively defined entities can easily exhaust all available
memory. Limit entity expansion to a default of 4096 characters to
avoid DoS attacks when a user loads untrusted content.
Added a setter and getter to allow modifying the expansion limit.
[ChangeLog][QtCore][QXmlStream] QXmlStreamReader does now by default
limit the expansion of entities to 4096 characters. Documents where
a single entity expands to more characters than the limit are not
considered well formed. The limit is there to avoid DoS attacks through
recursively expanding entities when loading untrusted content. The
limit can be changed through the QXmlStreamReader::setEntityExpansionLimit()
method.
Fixes: QTBUG-47417
Change-Id: I94387815d74fcf34783e136387ee57fac5ded0c9
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
---
src/corelib/serialization/qxmlstream.cpp | 36 ++++++++++++++++++
src/corelib/serialization/qxmlstream.g | 14 ++++++-
src/corelib/serialization/qxmlstream.h | 2 +
src/corelib/serialization/qxmlstream_p.h | 14 ++++++-
.../serialization/qxmlstream/tst_qxmlstream.cpp | 44 +++++++++++++++++++++-
5 files changed, 106 insertions(+), 4 deletions(-)
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index 7ff87885a5..d7fb0d0d41 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -2041,6 +2041,42 @@ QStringRef QXmlStreamReader::dtdSystemId() const
return QStringRef();
}
+/*!
+ \since 5.15
+
+ Returns the maximum amount of characters a single entity is
+ allowed to expand into. If a single entity expands past the
+ given limit, the document is not considered well formed.
+
+ \sa setEntityExpansionLimit
+*/
+int QXmlStreamReader::entityExpansionLimit() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->entityExpansionLimit;
+}
+
+/*!
+ \since 5.15
+
+ Sets the maximum amount of characters a single entity is
+ allowed to expand into to \a limit. If a single entity expands
+ past the given limit, the document is not considered well formed.
+
+ The limit is there to prevent DoS attacks when loading unknown
+ XML documents where recursive entity expansion could otherwise
+ exhaust all available memory.
+
+ The default value for this property is 4096 characters.
+
+ \sa entityExpansionLimit
+*/
+void QXmlStreamReader::setEntityExpansionLimit(int limit)
+{
+ Q_D(QXmlStreamReader);
+ d->entityExpansionLimit = limit;
+}
+
/*! If the tokenType() is \l StartElement, this function returns the
element's namespace declarations. Otherwise an empty vector is
returned.
diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
index 12ecc9bdb2..b623de9505 100644
--- a/src/corelib/serialization/qxmlstream.g
+++ b/src/corelib/serialization/qxmlstream.g
@@ -285,9 +285,19 @@ public:
QHash<QStringView, Entity> entityHash;
QHash<QStringView, Entity> parameterEntityHash;
QXmlStreamSimpleStack<Entity *>entityReferenceStack;
+ int entityExpansionLimit = 4096;
+ int entityLength = 0;
inline bool referenceEntity(Entity &entity) {
if (entity.isCurrentlyReferenced) {
- raiseWellFormedError(QXmlStream::tr("Recursive entity detected."));
+ raiseWellFormedError(QXmlStream::tr("Self-referencing entity detected."));
+ return false;
+ }
+ // entityLength represents the amount of additional characters the
+ // entity expands into (can be negative for e.g. &amp;). It's used to
+ // avoid DoS attacks through recursive entity expansions
+ entityLength += entity.value.size() - entity.name.size() - 2;
+ if (entityLength > entityExpansionLimit) {
+ raiseWellFormedError(QXmlStream::tr("Entity expands to more characters than the entity expansion limit."));
return false;
}
entity.isCurrentlyReferenced = true;
@@ -838,6 +848,8 @@ entity_done ::= ENTITY_DONE;
/.
case $rule_number:
entityReferenceStack.pop()->isCurrentlyReferenced = false;
+ if (entityReferenceStack.isEmpty())
+ entityLength = 0;
clearSym();
break;
./
diff --git a/src/corelib/serialization/qxmlstream.h b/src/corelib/serialization/qxmlstream.h
index 7d0aa64570..c8647e0465 100644
--- a/src/corelib/serialization/qxmlstream.h
+++ b/src/corelib/serialization/qxmlstream.h
@@ -426,6 +426,8 @@ public:
QStringRef dtdPublicId() const;
QStringRef dtdSystemId() const;
+ int entityExpansionLimit() const;
+ void setEntityExpansionLimit(int limit);
enum Error {
NoError,
diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
index 9c94e6d434..103b123b10 100644
--- a/src/corelib/serialization/qxmlstream_p.h
+++ b/src/corelib/serialization/qxmlstream_p.h
@@ -774,9 +774,19 @@ public:
QHash<QStringView, Entity> entityHash;
QHash<QStringView, Entity> parameterEntityHash;
QXmlStreamSimpleStack<Entity *>entityReferenceStack;
+ int entityExpansionLimit = 4096;
+ int entityLength = 0;
inline bool referenceEntity(Entity &entity) {
if (entity.isCurrentlyReferenced) {
- raiseWellFormedError(QXmlStream::tr("Recursive entity detected."));
+ raiseWellFormedError(QXmlStream::tr("Self-referencing entity detected."));
+ return false;
+ }
+ // entityLength represents the amount of additional characters the
+ // entity expands into (can be negative for e.g. &amp;). It's used to
+ // avoid DoS attacks through recursive entity expansions
+ entityLength += entity.value.size() - entity.name.size() - 2;
+ if (entityLength > entityExpansionLimit) {
+ raiseWellFormedError(QXmlStream::tr("Entity expands to more characters than the entity expansion limit."));
return false;
}
entity.isCurrentlyReferenced = true;
@@ -1308,6 +1318,8 @@ bool QXmlStreamReaderPrivate::parse()
case 10:
entityReferenceStack.pop()->isCurrentlyReferenced = false;
+ if (entityReferenceStack.isEmpty())
+ entityLength = 0;
clearSym();
break;

View File

@ -13,7 +13,7 @@
Name: qt5-qtbase Name: qt5-qtbase
Summary: Core component of Qt toolkit Summary: Core component of Qt toolkit
Version: 5.11.1 Version: 5.11.1
Release: 11 Release: 12
License: LGPLv2 with exceptions or GPLv3 with exceptions License: LGPLv2 with exceptions or GPLv3 with exceptions
Url: http://qt-project.org/ Url: http://qt-project.org/
Source0: https://download.qt.io/new_archive/qt/5.11/%{version}/submodules/qtbase-everywhere-src-%{version}.tar.xz Source0: https://download.qt.io/new_archive/qt/5.11/%{version}/submodules/qtbase-everywhere-src-%{version}.tar.xz
@ -36,6 +36,7 @@ Patch0010: qtbase-everywhere-src-5.11.1-python3.patch
Patch0011: qt5-qtbase-glibc.patch Patch0011: qt5-qtbase-glibc.patch
Patch6000: CVE-2018-15518.patch Patch6000: CVE-2018-15518.patch
Patch6001: CVE-2015-9541.patch
BuildRequires: pkgconfig(libsystemd) cups-devel desktop-file-utils findutils BuildRequires: pkgconfig(libsystemd) cups-devel desktop-file-utils findutils
BuildRequires: libjpeg-devel libmng-devel libtiff-devel pkgconfig(alsa) BuildRequires: libjpeg-devel libmng-devel libtiff-devel pkgconfig(alsa)
@ -402,6 +403,9 @@ fi
%changelog %changelog
* Mon Sep 21 2020 wutao <wutao61@huawei.com> - 5.11.1-12
- fix CVE-2015-9541
* Mon Sep 14 2020 liuweibo <liuweibo10@huawei.com> - 5.11.1-11 * Mon Sep 14 2020 liuweibo <liuweibo10@huawei.com> - 5.11.1-11
- Fix Source0 - Fix Source0