Gentoo Archives: gentoo-commits

From: "Davide Pesavento (pesa)" <pesa@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in dev-qt/qtcore/files: CVE-2013-4549-01-disallow-deep-or-widely-nested-entity-refs.patch CVE-2013-4549-02-fully-expand-entities.patch
Date: Sat, 28 Dec 2013 01:25:58
Message-Id: 20131228012552.9C3892004C@flycatcher.gentoo.org
1 pesa 13/12/28 01:25:52
2
3 Added:
4 CVE-2013-4549-01-disallow-deep-or-widely-nested-entity-refs.patch
5 CVE-2013-4549-02-fully-expand-entities.patch
6 Log:
7 Apply upstream patches for CVE-2013-4549.
8
9 (Portage version: 2.2.7/cvs/Linux x86_64, signed Manifest commit with key 17A85C72)
10
11 Revision Changes Path
12 1.1 dev-qt/qtcore/files/CVE-2013-4549-01-disallow-deep-or-widely-nested-entity-refs.patch
13
14 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-qt/qtcore/files/CVE-2013-4549-01-disallow-deep-or-widely-nested-entity-refs.patch?rev=1.1&view=markup
15 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-qt/qtcore/files/CVE-2013-4549-01-disallow-deep-or-widely-nested-entity-refs.patch?rev=1.1&content-type=text/plain
16
17 Index: CVE-2013-4549-01-disallow-deep-or-widely-nested-entity-refs.patch
18 ===================================================================
19 From 512a1ce0698d370c313bb561bbf078935fa0342e Mon Sep 17 00:00:00 2001
20 From: Mitch Curtis <mitch.curtis@×××××.com>
21 Date: Thu, 7 Nov 2013 09:36:29 +0100
22 Subject: Disallow deep or widely nested entity references.
23
24 Nested references with a depth of 2 or greater will fail. References
25 that partially expand to greater than 1024 characters will also fail.
26
27 This is a backport of 46a8885ae486e238a39efa5119c2714f328b08e4.
28
29 Change-Id: I0c2e1fa13d6ccb5f88641dae2ed3f28bfdeaf609
30 Reviewed-by: Richard J. Moore <rich@×××.org>
31 Reviewed-by: Lars Knoll <lars.knoll@×××××.com>
32
33 diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp
34 index a1777c5..3904632 100644
35 --- a/src/xml/sax/qxml.cpp
36 +++ b/src/xml/sax/qxml.cpp
37 @@ -424,6 +424,10 @@ private:
38 int stringValueLen;
39 QString emptyStr;
40
41 + // The limit to the amount of times the DTD parsing functions can be called
42 + // for the DTD currently being parsed.
43 + int dtdRecursionLimit;
44 +
45 const QString &string();
46 void stringClear();
47 void stringAddC(QChar);
48 @@ -492,6 +496,7 @@ private:
49 void unexpectedEof(ParseFunction where, int state);
50 void parseFailed(ParseFunction where, int state);
51 void pushParseState(ParseFunction function, int state);
52 + bool isPartiallyExpandedEntityValueTooLarge(QString *errorMessage);
53
54 Q_DECLARE_PUBLIC(QXmlSimpleReader)
55 QXmlSimpleReader *q_ptr;
56 @@ -2759,6 +2764,7 @@ QXmlSimpleReaderPrivate::QXmlSimpleReaderPrivate(QXmlSimpleReader *reader)
57 useNamespacePrefixes = false;
58 reportWhitespaceCharData = true;
59 reportEntities = false;
60 + dtdRecursionLimit = 2;
61 }
62
63 QXmlSimpleReaderPrivate::~QXmlSimpleReaderPrivate()
64 @@ -5018,6 +5024,11 @@ bool QXmlSimpleReaderPrivate::parseDoctype()
65 }
66 break;
67 case Mup:
68 + if (dtdRecursionLimit > 0 && parameterEntities.size() > dtdRecursionLimit) {
69 + reportParseError(QString::fromLatin1(
70 + "DTD parsing exceeded recursion limit of %1.").arg(dtdRecursionLimit));
71 + return false;
72 + }
73 if (!parseMarkupdecl()) {
74 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
75 return false;
76 @@ -6627,6 +6638,37 @@ bool QXmlSimpleReaderPrivate::parseChoiceSeq()
77 return false;
78 }
79
80 +bool QXmlSimpleReaderPrivate::isPartiallyExpandedEntityValueTooLarge(QString *errorMessage)
81 +{
82 + const QString value = string();
83 + QMap<QString, int> referencedEntityCounts;
84 + foreach (QString entityName, entities.keys()) {
85 + for (int i = 0; i < value.size() && i != -1; ) {
86 + i = value.indexOf(entityName, i);
87 + if (i != -1) {
88 + // The entityName we're currently trying to find
89 + // was matched in this string; increase our count.
90 + ++referencedEntityCounts[entityName];
91 + i += entityName.size();
92 + }
93 + }
94 + }
95 +
96 + foreach (QString entityName, referencedEntityCounts.keys()) {
97 + const int timesReferenced = referencedEntityCounts[entityName];
98 + const QString entityValue = entities[entityName];
99 + if (entityValue.size() * timesReferenced > 1024) {
100 + if (errorMessage) {
101 + *errorMessage = QString::fromLatin1("The XML entity \"%1\""
102 + "expands too a string that is too large to process when "
103 + "referencing \"%2\" %3 times.").arg(entityName).arg(entityName).arg(timesReferenced);
104 + }
105 + return true;
106 + }
107 + }
108 + return false;
109 +}
110 +
111 /*
112 Parse a EntityDecl [70].
113
114 @@ -6721,6 +6763,15 @@ bool QXmlSimpleReaderPrivate::parseEntityDecl()
115 switch (state) {
116 case EValue:
117 if ( !entityExist(name())) {
118 + QString errorMessage;
119 + if (isPartiallyExpandedEntityValueTooLarge(&errorMessage)) {
120 + // The entity at entityName is entityValue.size() characters
121 + // long in its unexpanded form, and was mentioned timesReferenced times,
122 + // resulting in a string that would be greater than 1024 characters.
123 + reportParseError(errorMessage);
124 + return false;
125 + }
126 +
127 entities.insert(name(), string());
128 if (declHnd) {
129 if (!declHnd->internalEntityDecl(name(), string())) {
130 --
131 1.8.5.2
132
133
134
135
136 1.1 dev-qt/qtcore/files/CVE-2013-4549-02-fully-expand-entities.patch
137
138 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-qt/qtcore/files/CVE-2013-4549-02-fully-expand-entities.patch?rev=1.1&view=markup
139 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-qt/qtcore/files/CVE-2013-4549-02-fully-expand-entities.patch?rev=1.1&content-type=text/plain
140
141 Index: CVE-2013-4549-02-fully-expand-entities.patch
142 ===================================================================
143 From cecceb0cdd87482124a73ecf537f3445d68be13e Mon Sep 17 00:00:00 2001
144 From: Mitch Curtis <mitch.curtis@×××××.com>
145 Date: Tue, 12 Nov 2013 13:44:56 +0100
146 Subject: Fully expand entities to ensure deep or widely nested ones fail
147 parsing
148
149 With 512a1ce0698d370c313bb561bbf078935fa0342e, we failed when parsing
150 entities whose partially expanded size was greater than 1024
151 characters. That was not enough, so now we fully expand all entities.
152
153 This is a backport of f1053d94f59f053ce4acad9320df14f1fbe4faac.
154
155 Change-Id: I41dd6f4525c63e82fd320a22d19248169627f7e0
156 Reviewed-by: Richard J. Moore <rich@×××.org>
157
158 diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp
159 index 3904632..befa801 100644
160 --- a/src/xml/sax/qxml.cpp
161 +++ b/src/xml/sax/qxml.cpp
162 @@ -426,7 +426,9 @@ private:
163
164 // The limit to the amount of times the DTD parsing functions can be called
165 // for the DTD currently being parsed.
166 - int dtdRecursionLimit;
167 + static const int dtdRecursionLimit = 2;
168 + // The maximum amount of characters an entity value may contain, after expansion.
169 + static const int entityCharacterLimit = 1024;
170
171 const QString &string();
172 void stringClear();
173 @@ -496,7 +498,7 @@ private:
174 void unexpectedEof(ParseFunction where, int state);
175 void parseFailed(ParseFunction where, int state);
176 void pushParseState(ParseFunction function, int state);
177 - bool isPartiallyExpandedEntityValueTooLarge(QString *errorMessage);
178 + bool isExpandedEntityValueTooLarge(QString *errorMessage);
179
180 Q_DECLARE_PUBLIC(QXmlSimpleReader)
181 QXmlSimpleReader *q_ptr;
182 @@ -2764,7 +2766,6 @@ QXmlSimpleReaderPrivate::QXmlSimpleReaderPrivate(QXmlSimpleReader *reader)
183 useNamespacePrefixes = false;
184 reportWhitespaceCharData = true;
185 reportEntities = false;
186 - dtdRecursionLimit = 2;
187 }
188
189 QXmlSimpleReaderPrivate::~QXmlSimpleReaderPrivate()
190 @@ -6638,30 +6639,43 @@ bool QXmlSimpleReaderPrivate::parseChoiceSeq()
191 return false;
192 }
193
194 -bool QXmlSimpleReaderPrivate::isPartiallyExpandedEntityValueTooLarge(QString *errorMessage)
195 +bool QXmlSimpleReaderPrivate::isExpandedEntityValueTooLarge(QString *errorMessage)
196 {
197 - const QString value = string();
198 - QMap<QString, int> referencedEntityCounts;
199 - foreach (QString entityName, entities.keys()) {
200 - for (int i = 0; i < value.size() && i != -1; ) {
201 - i = value.indexOf(entityName, i);
202 - if (i != -1) {
203 - // The entityName we're currently trying to find
204 - // was matched in this string; increase our count.
205 - ++referencedEntityCounts[entityName];
206 - i += entityName.size();
207 + QMap<QString, int> literalEntitySizes;
208 + // The entity at (QMap<QString,) referenced the entities at (QMap<QString,) (int>) times.
209 + QMap<QString, QMap<QString, int> > referencesToOtherEntities;
210 + QMap<QString, int> expandedSizes;
211 +
212 + // For every entity, check how many times all entity names were referenced in its value.
213 + foreach (QString toSearch, entities.keys()) {
214 + // The amount of characters that weren't entity names, but literals, like 'X'.
215 + QString leftOvers = entities.value(toSearch);
216 + // How many times was entityName referenced by toSearch?
217 + foreach (QString entityName, entities.keys()) {
218 + for (int i = 0; i < leftOvers.size() && i != -1; ) {
219 + i = leftOvers.indexOf(QString::fromLatin1("&%1;").arg(entityName), i);
220 + if (i != -1) {
221 + leftOvers.remove(i, entityName.size() + 2);
222 + // The entityName we're currently trying to find was matched in this string; increase our count.
223 + ++referencesToOtherEntities[toSearch][entityName];
224 + }
225 }
226 }
227 + literalEntitySizes[toSearch] = leftOvers.size();
228 }
229
230 - foreach (QString entityName, referencedEntityCounts.keys()) {
231 - const int timesReferenced = referencedEntityCounts[entityName];
232 - const QString entityValue = entities[entityName];
233 - if (entityValue.size() * timesReferenced > 1024) {
234 + foreach (QString entity, referencesToOtherEntities.keys()) {
235 + expandedSizes[entity] = literalEntitySizes[entity];
236 + foreach (QString referenceTo, referencesToOtherEntities.value(entity).keys()) {
237 + const int references = referencesToOtherEntities.value(entity).value(referenceTo);
238 + // The total size of an entity's value is the expanded size of all of its referenced entities, plus its literal size.
239 + expandedSizes[entity] += expandedSizes[referenceTo] * references + literalEntitySizes[referenceTo] * references;
240 + }
241 +
242 + if (expandedSizes[entity] > entityCharacterLimit) {
243 if (errorMessage) {
244 - *errorMessage = QString::fromLatin1("The XML entity \"%1\""
245 - "expands too a string that is too large to process when "
246 - "referencing \"%2\" %3 times.").arg(entityName).arg(entityName).arg(timesReferenced);
247 + *errorMessage = QString::fromLatin1("The XML entity \"%1\" expands too a string that is too large to process (%2 characters > %3).");
248 + *errorMessage = (*errorMessage).arg(entity).arg(expandedSizes[entity]).arg(entityCharacterLimit);
249 }
250 return true;
251 }
252 @@ -6764,10 +6778,7 @@ bool QXmlSimpleReaderPrivate::parseEntityDecl()
253 case EValue:
254 if ( !entityExist(name())) {
255 QString errorMessage;
256 - if (isPartiallyExpandedEntityValueTooLarge(&errorMessage)) {
257 - // The entity at entityName is entityValue.size() characters
258 - // long in its unexpanded form, and was mentioned timesReferenced times,
259 - // resulting in a string that would be greater than 1024 characters.
260 + if (isExpandedEntityValueTooLarge(&errorMessage)) {
261 reportParseError(errorMessage);
262 return false;
263 }
264 --
265 1.8.5.2