summarylogtreecommitdiffstats
path: root/CVE-2013-4549.patch
diff options
context:
space:
mode:
authorFelix Schindler2015-06-20 15:54:41 +0200
committerFelix Schindler2015-06-20 15:54:41 +0200
commitb6f4064f95efba89cb564fb56d697944b014a5a5 (patch)
tree5af7284169336059dd8efd3e2c98d9690ecdd156 /CVE-2013-4549.patch
downloadaur-b6f4064f95efba89cb564fb56d697944b014a5a5.tar.gz
add state of https://github.com/ftalbrecht/aur, rev. 84761b9
Diffstat (limited to 'CVE-2013-4549.patch')
-rw-r--r--CVE-2013-4549.patch235
1 files changed, 235 insertions, 0 deletions
diff --git a/CVE-2013-4549.patch b/CVE-2013-4549.patch
new file mode 100644
index 000000000000..6111aa8fe10f
--- /dev/null
+++ b/CVE-2013-4549.patch
@@ -0,0 +1,235 @@
+From 46a8885ae486e238a39efa5119c2714f328b08e4 Mon Sep 17 00:00:00 2001
+From: Mitch Curtis <mitch.curtis@digia.com>
+Date: Fri, 27 Sep 2013 12:32:28 +0200
+Subject: [PATCH] Disallow deep or widely nested entity references.
+
+Nested references with a depth of 2 or greater will fail. References
+that partially expand to greater than 1024 characters will also fail.
+
+Change-Id: Id4e49d6f7cf51e3a247efdb4c6c7c9bd9b223f6e
+Reviewed-by: Richard J. Moore <rich@kde.org>
+Reviewed-by: Lars Knoll <lars.knoll@digia.com>
+
+From f1053d94f59f053ce4acad9320df14f1fbe4faac Mon Sep 17 00:00:00 2001
+From: Mitch Curtis <mitch.curtis@digia.com>
+Date: Mon, 11 Nov 2013 14:27:40 +0100
+Subject: [PATCH] Fully expand entities to ensure deep or widely nested ones fail parsing
+
+With 46a8885ae486e238a39efa5119c2714f328b08e4, we failed when parsing
+entities whose partially expanded size was greater than 1024
+characters. That was not enough, so now we fully expand all entities.
+
+Amends 46a8885ae486e238a39efa5119c2714f328b08e4.
+
+Change-Id: Ie80720d7e04d825eb4eebf528140eb94806c02b1
+Reviewed-by: Richard J. Moore <rich@kde.org>
+Reviewed-by: Lars Knoll <lars.knoll@digia.com>
+
+diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp
+index 45c0f3e..e6d78d3 100644
+--- a/src/xml/sax/qxml.cpp
++++ b/src/xml/sax/qxml.cpp
+@@ -424,6 +424,10 @@ private:
+ int stringValueLen;
+ QString emptyStr;
+
++ // The limit to the amount of times the DTD parsing functions can be called
++ // for the DTD currently being parsed.
++ int dtdRecursionLimit;
++
+ const QString &string();
+ void stringClear();
+ void stringAddC(QChar);
+@@ -493,6 +497,8 @@ private:
+ void parseFailed(ParseFunction where, int state);
+ void pushParseState(ParseFunction function, int state);
+
++ bool isPartiallyExpandedEntityValueTooLarge(QString *errorMessage);
++
+ Q_DECLARE_PUBLIC(QXmlSimpleReader)
+ QXmlSimpleReader *q_ptr;
+
+@@ -2757,6 +2763,8 @@ QXmlSimpleReaderPrivate::QXmlSimpleReaderPrivate(QXmlSimpleReader *reader)
+ useNamespacePrefixes = false;
+ reportWhitespaceCharData = true;
+ reportEntities = false;
++
++ dtdRecursionLimit = 2;
+ }
+
+ QXmlSimpleReaderPrivate::~QXmlSimpleReaderPrivate()
+@@ -5035,6 +5043,11 @@ bool QXmlSimpleReaderPrivate::parseDoctype()
+ }
+ break;
+ case Mup:
++ if (dtdRecursionLimit > 0 && parameterEntities.size() > dtdRecursionLimit) {
++ reportParseError(QString::fromLatin1(
++ "DTD parsing exceeded recursion limit of %1.").arg(dtdRecursionLimit));
++ return false;
++ }
+ if (!parseMarkupdecl()) {
+ parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
+ return false;
+@@ -6644,6 +6657,37 @@ bool QXmlSimpleReaderPrivate::parseChoiceSeq()
+ return false;
+ }
+
++bool QXmlSimpleReaderPrivate::isPartiallyExpandedEntityValueTooLarge(QString *errorMessage)
++{
++ const QString value = string();
++ QMap<QString, int> referencedEntityCounts;
++ foreach (QString entityName, entities.keys()) {
++ for (int i = 0; i < value.size() && i != -1; ) {
++ i = value.indexOf(entityName, i);
++ if (i != -1) {
++ // The entityName we're currently trying to find
++ // was matched in this string; increase our count.
++ ++referencedEntityCounts[entityName];
++ i += entityName.size();
++ }
++ }
++ }
++
++ foreach (QString entityName, referencedEntityCounts.keys()) {
++ const int timesReferenced = referencedEntityCounts[entityName];
++ const QString entityValue = entities[entityName];
++ if (entityValue.size() * timesReferenced > 1024) {
++ if (errorMessage) {
++ *errorMessage = QString::fromLatin1("The XML entity \"%1\""
++ "expands too a string that is too large to process when "
++ "referencing \"%2\" %3 times.").arg(entityName).arg(entityName).arg(timesReferenced);
++ }
++ return true;
++ }
++ }
++ return false;
++}
++
+ /*
+ Parse a EntityDecl [70].
+
+@@ -6738,6 +6782,15 @@ bool QXmlSimpleReaderPrivate::parseEntityDecl()
+ switch (state) {
+ case EValue:
+ if ( !entityExist(name())) {
++ QString errorMessage;
++ if (isPartiallyExpandedEntityValueTooLarge(&errorMessage)) {
++ // The entity at entityName is entityValue.size() characters
++ // long in its unexpanded form, and was mentioned timesReferenced times,
++ // resulting in a string that would be greater than 1024 characters.
++ reportParseError(errorMessage);
++ return false;
++ }
++
+ entities.insert(name(), string());
+ if (declHnd) {
+ if (!declHnd->internalEntityDecl(name(), string())) {
+diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp
+index e6d78d3..f3a1e47 100644
+--- a/src/xml/sax/qxml.cpp
++++ b/src/xml/sax/qxml.cpp
+@@ -426,7 +426,9 @@ private:
+
+ // The limit to the amount of times the DTD parsing functions can be called
+ // for the DTD currently being parsed.
+- int dtdRecursionLimit;
++ static const int dtdRecursionLimit = 2;
++ // The maximum amount of characters an entity value may contain, after expansion.
++ static const int entityCharacterLimit = 1024;
+
+ const QString &string();
+ void stringClear();
+@@ -497,7 +499,7 @@ private:
+ void parseFailed(ParseFunction where, int state);
+ void pushParseState(ParseFunction function, int state);
+
+- bool isPartiallyExpandedEntityValueTooLarge(QString *errorMessage);
++ bool isExpandedEntityValueTooLarge(QString *errorMessage);
+
+ Q_DECLARE_PUBLIC(QXmlSimpleReader)
+ QXmlSimpleReader *q_ptr;
+@@ -2763,8 +2765,6 @@ QXmlSimpleReaderPrivate::QXmlSimpleReaderPrivate(QXmlSimpleReader *reader)
+ useNamespacePrefixes = false;
+ reportWhitespaceCharData = true;
+ reportEntities = false;
+-
+- dtdRecursionLimit = 2;
+ }
+
+ QXmlSimpleReaderPrivate::~QXmlSimpleReaderPrivate()
+@@ -6657,30 +6657,43 @@ bool QXmlSimpleReaderPrivate::parseChoiceSeq()
+ return false;
+ }
+
+-bool QXmlSimpleReaderPrivate::isPartiallyExpandedEntityValueTooLarge(QString *errorMessage)
++bool QXmlSimpleReaderPrivate::isExpandedEntityValueTooLarge(QString *errorMessage)
+ {
+- const QString value = string();
+- QMap<QString, int> referencedEntityCounts;
+- foreach (QString entityName, entities.keys()) {
+- for (int i = 0; i < value.size() && i != -1; ) {
+- i = value.indexOf(entityName, i);
+- if (i != -1) {
+- // The entityName we're currently trying to find
+- // was matched in this string; increase our count.
+- ++referencedEntityCounts[entityName];
+- i += entityName.size();
++ QMap<QString, int> literalEntitySizes;
++ // The entity at (QMap<QString,) referenced the entities at (QMap<QString,) (int>) times.
++ QMap<QString, QMap<QString, int> > referencesToOtherEntities;
++ QMap<QString, int> expandedSizes;
++
++ // For every entity, check how many times all entity names were referenced in its value.
++ foreach (QString toSearch, entities.keys()) {
++ // The amount of characters that weren't entity names, but literals, like 'X'.
++ QString leftOvers = entities.value(toSearch);
++ // How many times was entityName referenced by toSearch?
++ foreach (QString entityName, entities.keys()) {
++ for (int i = 0; i < leftOvers.size() && i != -1; ) {
++ i = leftOvers.indexOf(QString::fromLatin1("&%1;").arg(entityName), i);
++ if (i != -1) {
++ leftOvers.remove(i, entityName.size() + 2);
++ // The entityName we're currently trying to find was matched in this string; increase our count.
++ ++referencesToOtherEntities[toSearch][entityName];
++ }
+ }
+ }
++ literalEntitySizes[toSearch] = leftOvers.size();
+ }
+
+- foreach (QString entityName, referencedEntityCounts.keys()) {
+- const int timesReferenced = referencedEntityCounts[entityName];
+- const QString entityValue = entities[entityName];
+- if (entityValue.size() * timesReferenced > 1024) {
++ foreach (QString entity, referencesToOtherEntities.keys()) {
++ expandedSizes[entity] = literalEntitySizes[entity];
++ foreach (QString referenceTo, referencesToOtherEntities.value(entity).keys()) {
++ const int references = referencesToOtherEntities.value(entity).value(referenceTo);
++ // The total size of an entity's value is the expanded size of all of its referenced entities, plus its literal size.
++ expandedSizes[entity] += expandedSizes[referenceTo] * references + literalEntitySizes[referenceTo] * references;
++ }
++
++ if (expandedSizes[entity] > entityCharacterLimit) {
+ if (errorMessage) {
+- *errorMessage = QString::fromLatin1("The XML entity \"%1\""
+- "expands too a string that is too large to process when "
+- "referencing \"%2\" %3 times.").arg(entityName).arg(entityName).arg(timesReferenced);
++ *errorMessage = QString::fromLatin1("The XML entity \"%1\" expands too a string that is too large to process (%2 characters > %3).");
++ *errorMessage = (*errorMessage).arg(entity).arg(expandedSizes[entity]).arg(entityCharacterLimit);
+ }
+ return true;
+ }
+@@ -6783,10 +6796,7 @@ bool QXmlSimpleReaderPrivate::parseEntityDecl()
+ case EValue:
+ if ( !entityExist(name())) {
+ QString errorMessage;
+- if (isPartiallyExpandedEntityValueTooLarge(&errorMessage)) {
+- // The entity at entityName is entityValue.size() characters
+- // long in its unexpanded form, and was mentioned timesReferenced times,
+- // resulting in a string that would be greater than 1024 characters.
++ if (isExpandedEntityValueTooLarge(&errorMessage)) {
+ reportParseError(errorMessage);
+ return false;
+ }
+--
+1.7