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 |