|
1 From 459eeb9dc752d5185f57ff6b135027f11981a626 Mon Sep 17 00:00:00 2001 |
|
2 From: Daniel Veillard <[email protected]> |
|
3 Date: Tue, 17 Jul 2012 08:19:17 +0000 |
|
4 Subject: Fix parser local buffers size problems |
|
5 |
|
6 --- |
|
7 diff --git a/parser.c b/parser.c |
|
8 index 2c38fae..9863275 100644 |
|
9 --- a/parser.c |
|
10 +++ b/parser.c |
|
11 @@ -40,6 +40,7 @@ |
|
12 #endif |
|
13 |
|
14 #include <stdlib.h> |
|
15 +#include <limits.h> |
|
16 #include <string.h> |
|
17 #include <stdarg.h> |
|
18 #include <libxml/xmlmemory.h> |
|
19 @@ -117,10 +118,10 @@ xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID, |
|
20 * parser option. |
|
21 */ |
|
22 static int |
|
23 -xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size, |
|
24 +xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size, |
|
25 xmlEntityPtr ent) |
|
26 { |
|
27 - unsigned long consumed = 0; |
|
28 + size_t consumed = 0; |
|
29 |
|
30 if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE)) |
|
31 return (0); |
|
32 @@ -2589,15 +2590,17 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) { |
|
33 |
|
34 /* |
|
35 * Macro used to grow the current buffer. |
|
36 + * buffer##_size is expected to be a size_t |
|
37 + * mem_error: is expected to handle memory allocation failures |
|
38 */ |
|
39 #define growBuffer(buffer, n) { \ |
|
40 xmlChar *tmp; \ |
|
41 - buffer##_size *= 2; \ |
|
42 - buffer##_size += n; \ |
|
43 - tmp = (xmlChar *) \ |
|
44 - xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \ |
|
45 + size_t new_size = buffer##_size * 2 + n; \ |
|
46 + if (new_size < buffer##_size) goto mem_error; \ |
|
47 + tmp = (xmlChar *) xmlRealloc(buffer, new_size); \ |
|
48 if (tmp == NULL) goto mem_error; \ |
|
49 buffer = tmp; \ |
|
50 + buffer##_size = new_size; \ |
|
51 } |
|
52 |
|
53 /** |
|
54 @@ -2623,14 +2626,14 @@ xmlChar * |
|
55 xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, |
|
56 int what, xmlChar end, xmlChar end2, xmlChar end3) { |
|
57 xmlChar *buffer = NULL; |
|
58 - int buffer_size = 0; |
|
59 + size_t buffer_size = 0; |
|
60 + size_t nbchars = 0; |
|
61 |
|
62 xmlChar *current = NULL; |
|
63 xmlChar *rep = NULL; |
|
64 const xmlChar *last; |
|
65 xmlEntityPtr ent; |
|
66 int c,l; |
|
67 - int nbchars = 0; |
|
68 |
|
69 if ((ctxt == NULL) || (str == NULL) || (len < 0)) |
|
70 return(NULL); |
|
71 @@ -2647,7 +2650,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, |
|
72 * allocate a translation buffer. |
|
73 */ |
|
74 buffer_size = XML_PARSER_BIG_BUFFER_SIZE; |
|
75 - buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar)); |
|
76 + buffer = (xmlChar *) xmlMallocAtomic(buffer_size); |
|
77 if (buffer == NULL) goto mem_error; |
|
78 |
|
79 /* |
|
80 @@ -2667,7 +2670,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, |
|
81 if (val != 0) { |
|
82 COPY_BUF(0,buffer,nbchars,val); |
|
83 } |
|
84 - if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { |
|
85 + if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { |
|
86 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); |
|
87 } |
|
88 } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) { |
|
89 @@ -2685,7 +2688,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, |
|
90 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { |
|
91 if (ent->content != NULL) { |
|
92 COPY_BUF(0,buffer,nbchars,ent->content[0]); |
|
93 - if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { |
|
94 + if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { |
|
95 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); |
|
96 } |
|
97 } else { |
|
98 @@ -2702,8 +2705,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, |
|
99 current = rep; |
|
100 while (*current != 0) { /* non input consuming loop */ |
|
101 buffer[nbchars++] = *current++; |
|
102 - if (nbchars > |
|
103 - buffer_size - XML_PARSER_BUFFER_SIZE) { |
|
104 + if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { |
|
105 if (xmlParserEntityCheck(ctxt, nbchars, ent)) |
|
106 goto int_error; |
|
107 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); |
|
108 @@ -2717,7 +2719,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, |
|
109 const xmlChar *cur = ent->name; |
|
110 |
|
111 buffer[nbchars++] = '&'; |
|
112 - if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) { |
|
113 + if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) { |
|
114 growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE); |
|
115 } |
|
116 for (;i > 0;i--) |
|
117 @@ -2745,8 +2747,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, |
|
118 current = rep; |
|
119 while (*current != 0) { /* non input consuming loop */ |
|
120 buffer[nbchars++] = *current++; |
|
121 - if (nbchars > |
|
122 - buffer_size - XML_PARSER_BUFFER_SIZE) { |
|
123 + if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { |
|
124 if (xmlParserEntityCheck(ctxt, nbchars, ent)) |
|
125 goto int_error; |
|
126 growBuffer(buffer, XML_PARSER_BUFFER_SIZE); |
|
127 @@ -2759,8 +2760,8 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, |
|
128 } else { |
|
129 COPY_BUF(l,buffer,nbchars,c); |
|
130 str += l; |
|
131 - if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) { |
|
132 - growBuffer(buffer, XML_PARSER_BUFFER_SIZE); |
|
133 + if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { |
|
134 + growBuffer(buffer, XML_PARSER_BUFFER_SIZE); |
|
135 } |
|
136 } |
|
137 if (str < last) |
|
138 @@ -3764,8 +3765,8 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
139 xmlChar limit = 0; |
|
140 xmlChar *buf = NULL; |
|
141 xmlChar *rep = NULL; |
|
142 - int len = 0; |
|
143 - int buf_size = 0; |
|
144 + size_t len = 0; |
|
145 + size_t buf_size = 0; |
|
146 int c, l, in_space = 0; |
|
147 xmlChar *current = NULL; |
|
148 xmlEntityPtr ent; |
|
149 @@ -3787,7 +3788,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
150 * allocate a translation buffer. |
|
151 */ |
|
152 buf_size = XML_PARSER_BUFFER_SIZE; |
|
153 - buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar)); |
|
154 + buf = (xmlChar *) xmlMallocAtomic(buf_size); |
|
155 if (buf == NULL) goto mem_error; |
|
156 |
|
157 /* |
|
158 @@ -3804,7 +3805,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
159 |
|
160 if (val == '&') { |
|
161 if (ctxt->replaceEntities) { |
|
162 - if (len > buf_size - 10) { |
|
163 + if (len + 10 > buf_size) { |
|
164 growBuffer(buf, 10); |
|
165 } |
|
166 buf[len++] = '&'; |
|
167 @@ -3813,7 +3814,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
168 * The reparsing will be done in xmlStringGetNodeList() |
|
169 * called by the attribute() function in SAX.c |
|
170 */ |
|
171 - if (len > buf_size - 10) { |
|
172 + if (len + 10 > buf_size) { |
|
173 growBuffer(buf, 10); |
|
174 } |
|
175 buf[len++] = '&'; |
|
176 @@ -3823,7 +3824,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
177 buf[len++] = ';'; |
|
178 } |
|
179 } else if (val != 0) { |
|
180 - if (len > buf_size - 10) { |
|
181 + if (len + 10 > buf_size) { |
|
182 growBuffer(buf, 10); |
|
183 } |
|
184 len += xmlCopyChar(0, &buf[len], val); |
|
185 @@ -3835,7 +3836,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
186 ctxt->nbentities += ent->owner; |
|
187 if ((ent != NULL) && |
|
188 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { |
|
189 - if (len > buf_size - 10) { |
|
190 + if (len + 10 > buf_size) { |
|
191 growBuffer(buf, 10); |
|
192 } |
|
193 if ((ctxt->replaceEntities == 0) && |
|
194 @@ -3863,7 +3864,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
195 current++; |
|
196 } else |
|
197 buf[len++] = *current++; |
|
198 - if (len > buf_size - 10) { |
|
199 + if (len + 10 > buf_size) { |
|
200 growBuffer(buf, 10); |
|
201 } |
|
202 } |
|
203 @@ -3871,7 +3872,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
204 rep = NULL; |
|
205 } |
|
206 } else { |
|
207 - if (len > buf_size - 10) { |
|
208 + if (len + 10 > buf_size) { |
|
209 growBuffer(buf, 10); |
|
210 } |
|
211 if (ent->content != NULL) |
|
212 @@ -3899,7 +3900,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
213 * Just output the reference |
|
214 */ |
|
215 buf[len++] = '&'; |
|
216 - while (len > buf_size - i - 10) { |
|
217 + while (len + i + 10 > buf_size) { |
|
218 growBuffer(buf, i + 10); |
|
219 } |
|
220 for (;i > 0;i--) |
|
221 @@ -3912,7 +3913,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
222 if ((len != 0) || (!normalize)) { |
|
223 if ((!normalize) || (!in_space)) { |
|
224 COPY_BUF(l,buf,len,0x20); |
|
225 - while (len > buf_size - 10) { |
|
226 + while (len + 10 > buf_size) { |
|
227 growBuffer(buf, 10); |
|
228 } |
|
229 } |
|
230 @@ -3921,7 +3922,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
231 } else { |
|
232 in_space = 0; |
|
233 COPY_BUF(l,buf,len,c); |
|
234 - if (len > buf_size - 10) { |
|
235 + if (len + 10 > buf_size) { |
|
236 growBuffer(buf, 10); |
|
237 } |
|
238 } |
|
239 @@ -3946,7 +3947,18 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { |
|
240 } |
|
241 } else |
|
242 NEXT; |
|
243 - if (attlen != NULL) *attlen = len; |
|
244 + |
|
245 + /* |
|
246 + * There we potentially risk an overflow, don't allow attribute value of |
|
247 + * lenght more than INT_MAX it is a very reasonnable assumption ! |
|
248 + */ |
|
249 + if (len >= INT_MAX) { |
|
250 + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, |
|
251 + "AttValue lenght too long\n"); |
|
252 + goto mem_error; |
|
253 + } |
|
254 + |
|
255 + if (attlen != NULL) *attlen = (int) len; |
|
256 return(buf); |
|
257 |
|
258 mem_error: |
|
259 -- |
|
260 cgit v0.9.0.2 |