1 |
hoffie 08/02/02 22:22:40 |
2 |
|
3 |
Added: icu-3.6-regexp-CVE-2007-4770+4771.diff |
4 |
Log: |
5 |
adding patch (by redhat) for CVE-2007-{4770,4771} per bug #208001 for 3.6 series as well |
6 |
(Portage version: 2.1.4.1) |
7 |
|
8 |
Revision Changes Path |
9 |
1.1 dev-libs/icu/files/icu-3.6-regexp-CVE-2007-4770+4771.diff |
10 |
|
11 |
file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/dev-libs/icu/files/icu-3.6-regexp-CVE-2007-4770+4771.diff?rev=1.1&view=markup |
12 |
plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/dev-libs/icu/files/icu-3.6-regexp-CVE-2007-4770+4771.diff?rev=1.1&content-type=text/plain |
13 |
|
14 |
Index: icu-3.6-regexp-CVE-2007-4770+4771.diff |
15 |
=================================================================== |
16 |
# borrowed from redhat -- https://bugzilla.redhat.com/show_bug.cgi?id=429023 |
17 |
|
18 |
diff -ru icu.orig/source/common/uvectr32.cpp icu/source/common/uvectr32.cpp |
19 |
--- icu.orig/source/common/uvectr32.cpp 2003-08-27 02:01:30.000000000 +0100 |
20 |
+++ icu/source/common/uvectr32.cpp 2008-01-22 08:37:06.000000000 +0000 |
21 |
@@ -1,6 +1,6 @@ |
22 |
/* |
23 |
****************************************************************************** |
24 |
-* Copyright (C) 1999-2003, International Business Machines Corporation and * |
25 |
+* Copyright (C) 1999-2008, International Business Machines Corporation and * |
26 |
* others. All Rights Reserved. * |
27 |
****************************************************************************** |
28 |
* Date Name Description |
29 |
@@ -26,6 +26,7 @@ |
30 |
UVector32::UVector32(UErrorCode &status) : |
31 |
count(0), |
32 |
capacity(0), |
33 |
+ maxCapacity(0), |
34 |
elements(NULL) |
35 |
{ |
36 |
_init(DEFUALT_CAPACITY, status); |
37 |
@@ -34,6 +35,7 @@ |
38 |
UVector32::UVector32(int32_t initialCapacity, UErrorCode &status) : |
39 |
count(0), |
40 |
capacity(0), |
41 |
+ maxCapacity(0), |
42 |
elements(0) |
43 |
{ |
44 |
_init(initialCapacity, status); |
45 |
@@ -46,6 +48,9 @@ |
46 |
if (initialCapacity < 1) { |
47 |
initialCapacity = DEFUALT_CAPACITY; |
48 |
} |
49 |
+ if (maxCapacity>0 && maxCapacity<initialCapacity) { |
50 |
+ initialCapacity = maxCapacity; |
51 |
+ } |
52 |
elements = (int32_t *)uprv_malloc(sizeof(int32_t)*initialCapacity); |
53 |
if (elements == 0) { |
54 |
status = U_MEMORY_ALLOCATION_ERROR; |
55 |
@@ -189,21 +194,35 @@ |
56 |
UBool UVector32::expandCapacity(int32_t minimumCapacity, UErrorCode &status) { |
57 |
if (capacity >= minimumCapacity) { |
58 |
return TRUE; |
59 |
- } else { |
60 |
- int32_t newCap = capacity * 2; |
61 |
- if (newCap < minimumCapacity) { |
62 |
- newCap = minimumCapacity; |
63 |
- } |
64 |
- int32_t* newElems = (int32_t *)uprv_malloc(sizeof(int32_t)*newCap); |
65 |
- if (newElems == 0) { |
66 |
- status = U_MEMORY_ALLOCATION_ERROR; |
67 |
- return FALSE; |
68 |
- } |
69 |
- uprv_memcpy(newElems, elements, sizeof(elements[0]) * count); |
70 |
- uprv_free(elements); |
71 |
- elements = newElems; |
72 |
- capacity = newCap; |
73 |
- return TRUE; |
74 |
+ } |
75 |
+ if (maxCapacity>0 && minimumCapacity>maxCapacity) { |
76 |
+ status = U_BUFFER_OVERFLOW_ERROR; |
77 |
+ return FALSE; |
78 |
+ } |
79 |
+ int32_t newCap = capacity * 2; |
80 |
+ if (newCap < minimumCapacity) { |
81 |
+ newCap = minimumCapacity; |
82 |
+ } |
83 |
+ if (maxCapacity > 0 && newCap > maxCapacity) { |
84 |
+ newCap = maxCapacity; |
85 |
+ } |
86 |
+ int32_t* newElems = (int32_t *)uprv_malloc(sizeof(int32_t)*newCap); |
87 |
+ if (newElems == 0) { |
88 |
+ status = U_MEMORY_ALLOCATION_ERROR; |
89 |
+ return FALSE; |
90 |
+ } |
91 |
+ uprv_memcpy(newElems, elements, sizeof(elements[0]) * count); |
92 |
+ uprv_free(elements); |
93 |
+ elements = newElems; |
94 |
+ capacity = newCap; |
95 |
+ return TRUE; |
96 |
+} |
97 |
+ |
98 |
+void UVector32::setMaxCapacity(int32_t limit) { |
99 |
+ U_ASSERT(limit >= 0); |
100 |
+ maxCapacity = limit; |
101 |
+ if (maxCapacity < 0) { |
102 |
+ maxCapacity = 0; |
103 |
} |
104 |
} |
105 |
|
106 |
diff -ru icu.orig/source/common/uvectr32.h icu/source/common/uvectr32.h |
107 |
--- icu.orig/source/common/uvectr32.h 2006-01-18 03:52:04.000000000 +0000 |
108 |
+++ icu/source/common/uvectr32.h 2008-01-22 08:37:07.000000000 +0000 |
109 |
@@ -1,6 +1,6 @@ |
110 |
/* |
111 |
********************************************************************** |
112 |
-* Copyright (C) 1999-2006, International Business Machines |
113 |
+* Copyright (C) 1999-2008, International Business Machines |
114 |
* Corporation and others. All Rights Reserved. |
115 |
********************************************************************** |
116 |
*/ |
117 |
@@ -61,6 +61,8 @@ |
118 |
int32_t count; |
119 |
|
120 |
int32_t capacity; |
121 |
+ |
122 |
+ int32_t maxCapacity; // Limit beyond which capacity is not permitted to grow. |
123 |
|
124 |
int32_t* elements; |
125 |
|
126 |
@@ -162,6 +164,14 @@ |
127 |
int32_t *getBuffer() const; |
128 |
|
129 |
/** |
130 |
+ * Set the maximum allowed buffer capacity for this vector/stack. |
131 |
+ * Default with no limit set is unlimited, go until malloc() fails. |
132 |
+ * A Limit of zero means unlimited capacity. |
133 |
+ * Units are vector elements (32 bits each), not bytes. |
134 |
+ */ |
135 |
+ void setMaxCapacity(int32_t limit); |
136 |
+ |
137 |
+ /** |
138 |
* ICU "poor man's RTTI", returns a UClassID for this class. |
139 |
*/ |
140 |
static UClassID U_EXPORT2 getStaticClassID(); |
141 |
@@ -221,7 +231,9 @@ |
142 |
} |
143 |
|
144 |
inline int32_t *UVector32::reserveBlock(int32_t size, UErrorCode &status) { |
145 |
- ensureCapacity(count+size, status); |
146 |
+ if (ensureCapacity(count+size, status) == FALSE) { |
147 |
+ return NULL; |
148 |
+ } |
149 |
int32_t *rp = elements+count; |
150 |
count += size; |
151 |
return rp; |
152 |
diff -ru icu.orig/source/i18n/regexcmp.cpp icu/source/i18n/regexcmp.cpp |
153 |
--- icu.orig/source/i18n/regexcmp.cpp 2006-02-02 04:37:14.000000000 +0000 |
154 |
+++ icu/source/i18n/regexcmp.cpp 2008-01-22 08:37:06.000000000 +0000 |
155 |
@@ -1187,14 +1187,17 @@ |
156 |
// Because capture groups can be forward-referenced by back-references, |
157 |
// we fill the operand with the capture group number. At the end |
158 |
// of compilation, it will be changed to the variable's location. |
159 |
- U_ASSERT(groupNum > 0); |
160 |
- int32_t op; |
161 |
- if (fModeFlags & UREGEX_CASE_INSENSITIVE) { |
162 |
- op = URX_BUILD(URX_BACKREF_I, groupNum); |
163 |
+ if (groupNum < 1) { |
164 |
+ error(U_REGEX_INVALID_BACK_REF); |
165 |
} else { |
166 |
- op = URX_BUILD(URX_BACKREF, groupNum); |
167 |
+ int32_t op; |
168 |
+ if (fModeFlags & UREGEX_CASE_INSENSITIVE) { |
169 |
+ op = URX_BUILD(URX_BACKREF_I, groupNum); |
170 |
+ } else { |
171 |
+ op = URX_BUILD(URX_BACKREF, groupNum); |
172 |
+ } |
173 |
+ fRXPat->fCompiledPat->addElement(op, *fStatus); |
174 |
} |
175 |
- fRXPat->fCompiledPat->addElement(op, *fStatus); |
176 |
} |
177 |
break; |
178 |
|
179 |
diff -ru icu.orig/source/i18n/rematch.cpp icu/source/i18n/rematch.cpp |
180 |
--- icu.orig/source/i18n/rematch.cpp 2005-08-25 19:02:20.000000000 +0100 |
181 |
+++ icu/source/i18n/rematch.cpp 2008-01-22 08:37:44.000000000 +0000 |
182 |
@@ -30,6 +30,15 @@ |
183 |
|
184 |
U_NAMESPACE_BEGIN |
185 |
|
186 |
+// Limit the size of the back track stack, to avoid system failures caused |
187 |
+// by heap exhaustion. Units are in 32 bit words, not bytes. |
188 |
+// This value puts ICU's limits higher than most other regexp implementations, |
189 |
+// which use recursion rather than the heap, and take more storage per |
190 |
+// backtrack point. |
191 |
+// This constant is _temporary_. Proper API to control the value will added. |
192 |
+// |
193 |
+static const int32_t BACKTRACK_STACK_CAPACITY = 8000000; |
194 |
+ |
195 |
//----------------------------------------------------------------------------- |
196 |
// |
197 |
// Constructor and Destructor |
198 |
@@ -53,6 +62,8 @@ |
199 |
} |
200 |
if (fStack == NULL || fData == NULL) { |
201 |
fDeferredStatus = U_MEMORY_ALLOCATION_ERROR; |
202 |
+ } else { |
203 |
+ fStack->setMaxCapacity(BACKTRACK_STACK_CAPACITY); |
204 |
} |
205 |
|
206 |
reset(*RegexStaticSets::gStaticSets->fEmptyString); |
207 |
@@ -78,6 +89,8 @@ |
208 |
} |
209 |
if (fStack == NULL || fData == NULL) { |
210 |
status = U_MEMORY_ALLOCATION_ERROR; |
211 |
+ } else { |
212 |
+ fStack->setMaxCapacity(BACKTRACK_STACK_CAPACITY); |
213 |
} |
214 |
reset(input); |
215 |
} |
216 |
@@ -102,6 +115,8 @@ |
217 |
} |
218 |
if (fStack == NULL || fData == NULL) { |
219 |
status = U_MEMORY_ALLOCATION_ERROR; |
220 |
+ } else { |
221 |
+ fStack->setMaxCapacity(BACKTRACK_STACK_CAPACITY); |
222 |
} |
223 |
reset(*RegexStaticSets::gStaticSets->fEmptyString); |
224 |
} |
225 |
@@ -1015,6 +1030,14 @@ |
226 |
inline REStackFrame *RegexMatcher::StateSave(REStackFrame *fp, int32_t savePatIdx, int32_t frameSize, UErrorCode &status) { |
227 |
// push storage for a new frame. |
228 |
int32_t *newFP = fStack->reserveBlock(frameSize, status); |
229 |
+ if (newFP == NULL) { |
230 |
+ // Heap allocation error on attempted stack expansion. |
231 |
+ // We need to return a writable stack frame, so just return the |
232 |
+ // previous frame. The match operation will stop quickly |
233 |
+ // becuase of the error status, after which the frame will never |
234 |
+ // be looked at again. |
235 |
+ return fp; |
236 |
+ } |
237 |
fp = (REStackFrame *)(newFP - frameSize); // in case of realloc of stack. |
238 |
|
239 |
// New stack frame = copy of old top frame. |
240 |
@@ -1030,8 +1053,8 @@ |
241 |
fp->fPatIdx = savePatIdx; |
242 |
return (REStackFrame *)newFP; |
243 |
} |
244 |
- |
245 |
- |
246 |
+ |
247 |
+ |
248 |
//-------------------------------------------------------------------------------- |
249 |
// |
250 |
// MatchAt This is the actual matching engine. |
251 |
@@ -2262,6 +2285,7 @@ |
252 |
} |
253 |
|
254 |
if (U_FAILURE(status)) { |
255 |
+ isMatch = FALSE; |
256 |
break; |
257 |
} |
258 |
} |
259 |
diff -ru icu.orig/source/test/intltest/regextst.cpp icu/source/test/intltest/regextst.cpp |
260 |
--- icu.orig/source/test/intltest/regextst.cpp 2005-07-05 19:39:00.000000000 +0100 |
261 |
+++ icu/source/test/intltest/regextst.cpp 2008-01-22 08:38:21.000000000 +0000 |
262 |
@@ -66,6 +66,10 @@ |
263 |
case 6: name = "PerlTests"; |
264 |
if (exec) PerlTests(); |
265 |
break; |
266 |
+ case 7: name = "Bug 6149"; |
267 |
+ if (exec) Bug6149(); |
268 |
+ break; |
269 |
+ |
270 |
|
271 |
|
272 |
default: name = ""; |
273 |
@@ -1637,6 +1641,13 @@ |
274 |
// UnicodeSet containing a string |
275 |
REGEX_ERR("abc[{def}]xyz", 1, 10, U_REGEX_SET_CONTAINS_STRING); |
276 |
|
277 |
+ |
278 |
+ // Invalid Back Reference \0 |
279 |
+ // For ICU 3.8 and earlier |
280 |
+ // For ICU versions newer than 3.8, \0 introduces an octal escape. |
281 |
+ // |
282 |
+ REGEX_ERR("(ab)\\0", 1, 6, U_REGEX_INVALID_BACK_REF); |
283 |
+ |
284 |
} |
285 |
|
286 |
|
287 |
@@ -2119,6 +2130,26 @@ |
288 |
} |
289 |
|
290 |
|
291 |
+//-------------------------------------------------------------- |
292 |
+// |
293 |
+// Bug6149 Verify limits to heap expansion for backtrack stack. |
294 |
+// Use this pattern, |
295 |
+// "(a?){1,}" |
296 |
+// The zero-length match will repeat forever. |
297 |
+// (That this goes into a loop is another bug) |
298 |
+// |
299 |
+//--------------------------------------------------------------- |
300 |
+void RegexTest::Bug6149() { |
301 |
+ UnicodeString pattern("(a?){1,}"); |
302 |
+ UnicodeString s("xyz"); |
303 |
+ uint32_t flags = 0; |
304 |
+ UErrorCode status = U_ZERO_ERROR; |
305 |
+ |
306 |
+ RegexMatcher matcher(pattern, s, flags, status); |
307 |
+ UBool result = false; |
308 |
+ REGEX_ASSERT_FAIL(result=matcher.matches(status), U_BUFFER_OVERFLOW_ERROR); |
309 |
+ REGEX_ASSERT(result == FALSE); |
310 |
+ } |
311 |
|
312 |
#endif /* !UCONFIG_NO_REGULAR_EXPRESSIONS */ |
313 |
|
314 |
diff -ru icu.orig/source/test/intltest/regextst.h icu/source/test/intltest/regextst.h |
315 |
--- icu.orig/source/test/intltest/regextst.h 2003-12-03 06:58:28.000000000 +0000 |
316 |
+++ icu/source/test/intltest/regextst.h 2008-01-22 08:37:06.000000000 +0000 |
317 |
@@ -30,6 +30,7 @@ |
318 |
virtual void Extended(); |
319 |
virtual void Errors(); |
320 |
virtual void PerlTests(); |
321 |
+ virtual void Bug6149(); |
322 |
|
323 |
// The following functions are internal to the regexp tests. |
324 |
virtual UBool doRegexLMTest(const char *pat, const char *text, UBool looking, UBool match, int line); |
325 |
|
326 |
|
327 |
|
328 |
-- |
329 |
gentoo-commits@l.g.o mailing list |