[package] libxml2: backport Debian patches to fix multiple CVEs
[openwrt/svn-archive/archive.git] / libs / libxml2 / patches / 001-debian_CVEs.patch
1 --- libxml2-2.7.8/dict.c 2010-10-12 08:25:31.000000000 +0200
2 +++ libxml2-2.7.8.patched/dict.c 2012-09-28 12:08:37.432414664 +0200
3 @@ -2,7 +2,7 @@
4 * dict.c: dictionary of reusable strings, just used to avoid allocation
5 * and freeing operations.
6 *
7 - * Copyright (C) 2003 Daniel Veillard.
8 + * Copyright (C) 2003-2012 Daniel Veillard.
9 *
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 @@ -19,6 +19,28 @@
13 #define IN_LIBXML
14 #include "libxml.h"
15
16 +#ifdef HAVE_STDLIB_H
17 +#include <stdlib.h>
18 +#endif
19 +#ifdef HAVE_TIME_H
20 +#include <time.h>
21 +#endif
22 +
23 +/*
24 + * Following http://www.ocert.org/advisories/ocert-2011-003.html
25 + * it seems that having hash randomization might be a good idea
26 + * when using XML with untrusted data
27 + * Note1: that it works correctly only if compiled with WITH_BIG_KEY
28 + * which is the default.
29 + * Note2: the fast function used for a small dict won't protect very
30 + * well but since the attack is based on growing a very big hash
31 + * list we will use the BigKey algo as soon as the hash size grows
32 + * over MIN_DICT_SIZE so this actually works
33 + */
34 +#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME)
35 +#define DICT_RANDOMIZATION
36 +#endif
37 +
38 #include <string.h>
39 #ifdef HAVE_STDINT_H
40 #include <stdint.h>
41 @@ -44,23 +66,23 @@
42 #define WITH_BIG_KEY
43
44 #ifdef WITH_BIG_KEY
45 -#define xmlDictComputeKey(dict, name, len) \
46 - (((dict)->size == MIN_DICT_SIZE) ? \
47 - xmlDictComputeFastKey(name, len) : \
48 - xmlDictComputeBigKey(name, len))
49 -
50 -#define xmlDictComputeQKey(dict, prefix, plen, name, len) \
51 - (((prefix) == NULL) ? \
52 - (xmlDictComputeKey(dict, name, len)) : \
53 - (((dict)->size == MIN_DICT_SIZE) ? \
54 - xmlDictComputeFastQKey(prefix, plen, name, len) : \
55 - xmlDictComputeBigQKey(prefix, plen, name, len)))
56 +#define xmlDictComputeKey(dict, name, len) \
57 + (((dict)->size == MIN_DICT_SIZE) ? \
58 + xmlDictComputeFastKey(name, len, (dict)->seed) : \
59 + xmlDictComputeBigKey(name, len, (dict)->seed))
60 +
61 +#define xmlDictComputeQKey(dict, prefix, plen, name, len) \
62 + (((prefix) == NULL) ? \
63 + (xmlDictComputeKey(dict, name, len)) : \
64 + (((dict)->size == MIN_DICT_SIZE) ? \
65 + xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) : \
66 + xmlDictComputeBigQKey(prefix, plen, name, len, (dict)->seed)))
67
68 #else /* !WITH_BIG_KEY */
69 -#define xmlDictComputeKey(dict, name, len) \
70 - xmlDictComputeFastKey(name, len)
71 -#define xmlDictComputeQKey(dict, prefix, plen, name, len) \
72 - xmlDictComputeFastQKey(prefix, plen, name, len)
73 +#define xmlDictComputeKey(dict, name, len) \
74 + xmlDictComputeFastKey(name, len, (dict)->seed)
75 +#define xmlDictComputeQKey(dict, prefix, plen, name, len) \
76 + xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed)
77 #endif /* WITH_BIG_KEY */
78
79 /*
80 @@ -98,6 +120,8 @@
81 xmlDictStringsPtr strings;
82
83 struct _xmlDict *subdict;
84 + /* used for randomization */
85 + int seed;
86 };
87
88 /*
89 @@ -125,6 +149,9 @@
90 if ((xmlDictMutex = xmlNewRMutex()) == NULL)
91 return(0);
92
93 +#ifdef DICT_RANDOMIZATION
94 + srand(time(NULL));
95 +#endif
96 xmlDictInitialized = 1;
97 return(1);
98 }
99 @@ -277,13 +304,13 @@
100 */
101
102 static uint32_t
103 -xmlDictComputeBigKey(const xmlChar* data, int namelen) {
104 +xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
105 uint32_t hash;
106 int i;
107
108 if (namelen <= 0 || data == NULL) return(0);
109
110 - hash = 0;
111 + hash = seed;
112
113 for (i = 0;i < namelen; i++) {
114 hash += data[i];
115 @@ -310,12 +337,12 @@
116 */
117 static unsigned long
118 xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
119 - const xmlChar *name, int len)
120 + const xmlChar *name, int len, int seed)
121 {
122 uint32_t hash;
123 int i;
124
125 - hash = 0;
126 + hash = seed;
127
128 for (i = 0;i < plen; i++) {
129 hash += prefix[i];
130 @@ -346,8 +373,8 @@
131 * for low hash table fill.
132 */
133 static unsigned long
134 -xmlDictComputeFastKey(const xmlChar *name, int namelen) {
135 - unsigned long value = 0L;
136 +xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
137 + unsigned long value = seed;
138
139 if (name == NULL) return(0);
140 value = *name;
141 @@ -381,9 +408,9 @@
142 */
143 static unsigned long
144 xmlDictComputeFastQKey(const xmlChar *prefix, int plen,
145 - const xmlChar *name, int len)
146 + const xmlChar *name, int len, int seed)
147 {
148 - unsigned long value = 0L;
149 + unsigned long value = (unsigned long) seed;
150
151 if (plen == 0)
152 value += 30 * (unsigned long) ':';
153 @@ -460,6 +487,11 @@
154 dict->subdict = NULL;
155 if (dict->dict) {
156 memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
157 +#ifdef DICT_RANDOMIZATION
158 + dict->seed = rand();
159 +#else
160 + dict->seed = 0;
161 +#endif
162 return(dict);
163 }
164 xmlFree(dict);
165 @@ -486,6 +518,7 @@
166 #ifdef DICT_DEBUG_PATTERNS
167 fprintf(stderr, "R");
168 #endif
169 + dict->seed = sub->seed;
170 dict->subdict = sub;
171 xmlDictReference(dict->subdict);
172 }
173 --- libxml2-2.7.8/encoding.c 2010-11-04 17:40:06.000000000 +0100
174 +++ libxml2-2.7.8.patched/encoding.c 2012-09-28 12:08:37.440414665 +0200
175 @@ -1928,7 +1928,7 @@
176 if (in == NULL) return(-1);
177
178 /* calculate space available */
179 - written = out->size - out->use;
180 + written = out->size - out->use - 1; /* count '\0' */
181 toconv = in->use;
182 /*
183 * echo '<?xml version="1.0" encoding="UCS4"?>' | wc -c => 38
184 @@ -2059,7 +2059,7 @@
185 toconv = in->use;
186 if (toconv == 0)
187 return (0);
188 - written = out->size - out->use;
189 + written = out->size - out->use - 1; /* count '\0' */
190 if (toconv * 2 >= written) {
191 xmlBufferGrow(out, out->size + toconv * 2);
192 written = out->size - out->use - 1;
193 --- libxml2-2.7.8/entities.c 2010-10-12 08:25:32.000000000 +0200
194 +++ libxml2-2.7.8.patched/entities.c 2012-09-28 12:08:37.432414664 +0200
195 @@ -528,13 +528,13 @@
196 * Macro used to grow the current buffer.
197 */
198 #define growBufferReentrant() { \
199 - buffer_size *= 2; \
200 - buffer = (xmlChar *) \
201 - xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); \
202 - if (buffer == NULL) { \
203 - xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");\
204 - return(NULL); \
205 - } \
206 + xmlChar *tmp; \
207 + size_t new_size = buffer_size * 2; \
208 + if (new_size < buffer_size) goto mem_error; \
209 + tmp = (xmlChar *) xmlRealloc(buffer, new_size); \
210 + if (tmp == NULL) goto mem_error; \
211 + buffer = tmp; \
212 + buffer_size = new_size; \
213 }
214
215
216 @@ -555,7 +555,7 @@
217 const xmlChar *cur = input;
218 xmlChar *buffer = NULL;
219 xmlChar *out = NULL;
220 - int buffer_size = 0;
221 + size_t buffer_size = 0;
222 int html = 0;
223
224 if (input == NULL) return(NULL);
225 @@ -574,8 +574,8 @@
226 out = buffer;
227
228 while (*cur != '\0') {
229 - if (out - buffer > buffer_size - 100) {
230 - int indx = out - buffer;
231 + size_t indx = out - buffer;
232 + if (indx + 100 > buffer_size) {
233
234 growBufferReentrant();
235 out = &buffer[indx];
236 @@ -692,6 +692,11 @@
237 }
238 *out = 0;
239 return(buffer);
240 +
241 +mem_error:
242 + xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");
243 + xmlFree(buffer);
244 + return(NULL);
245 }
246
247 /**
248 @@ -709,7 +714,7 @@
249 const xmlChar *cur = input;
250 xmlChar *buffer = NULL;
251 xmlChar *out = NULL;
252 - int buffer_size = 0;
253 + size_t buffer_size = 0;
254 if (input == NULL) return(NULL);
255
256 /*
257 @@ -724,8 +729,8 @@
258 out = buffer;
259
260 while (*cur != '\0') {
261 - if (out - buffer > buffer_size - 10) {
262 - int indx = out - buffer;
263 + size_t indx = out - buffer;
264 + if (indx + 10 > buffer_size) {
265
266 growBufferReentrant();
267 out = &buffer[indx];
268 @@ -774,6 +779,11 @@
269 }
270 *out = 0;
271 return(buffer);
272 +
273 +mem_error:
274 + xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed");
275 + xmlFree(buffer);
276 + return(NULL);
277 }
278
279 /**
280 --- libxml2-2.7.8/hash.c 2010-10-12 08:25:32.000000000 +0200
281 +++ libxml2-2.7.8.patched/hash.c 2012-09-28 12:08:37.392414663 +0200
282 @@ -3,7 +3,7 @@
283 *
284 * Reference: Your favorite introductory book on algorithms
285 *
286 - * Copyright (C) 2000 Bjorn Reese and Daniel Veillard.
287 + * Copyright (C) 2000,2012 Bjorn Reese and Daniel Veillard.
288 *
289 * Permission to use, copy, modify, and distribute this software for any
290 * purpose with or without fee is hereby granted, provided that the above
291 @@ -21,6 +21,22 @@
292 #include "libxml.h"
293
294 #include <string.h>
295 +#ifdef HAVE_STDLIB_H
296 +#include <stdlib.h>
297 +#endif
298 +#ifdef HAVE_TIME_H
299 +#include <time.h>
300 +#endif
301 +
302 +/*
303 + * Following http://www.ocert.org/advisories/ocert-2011-003.html
304 + * it seems that having hash randomization might be a good idea
305 + * when using XML with untrusted data
306 + */
307 +#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME)
308 +#define HASH_RANDOMIZATION
309 +#endif
310 +
311 #include <libxml/parser.h>
312 #include <libxml/hash.h>
313 #include <libxml/xmlmemory.h>
314 @@ -31,6 +47,10 @@
315
316 /* #define DEBUG_GROW */
317
318 +#ifdef HASH_RANDOMIZATION
319 +static int hash_initialized = 0;
320 +#endif
321 +
322 /*
323 * A single entry in the hash table
324 */
325 @@ -53,6 +73,9 @@
326 int size;
327 int nbElems;
328 xmlDictPtr dict;
329 +#ifdef HASH_RANDOMIZATION
330 + int random_seed;
331 +#endif
332 };
333
334 /*
335 @@ -65,6 +88,9 @@
336 unsigned long value = 0L;
337 char ch;
338
339 +#ifdef HASH_RANDOMIZATION
340 + value = table->random_seed;
341 +#endif
342 if (name != NULL) {
343 value += 30 * (*name);
344 while ((ch = *name++) != 0) {
345 @@ -92,6 +118,9 @@
346 unsigned long value = 0L;
347 char ch;
348
349 +#ifdef HASH_RANDOMIZATION
350 + value = table->random_seed;
351 +#endif
352 if (prefix != NULL)
353 value += 30 * (*prefix);
354 else
355 @@ -156,6 +185,13 @@
356 table->table = xmlMalloc(size * sizeof(xmlHashEntry));
357 if (table->table) {
358 memset(table->table, 0, size * sizeof(xmlHashEntry));
359 +#ifdef HASH_RANDOMIZATION
360 + if (!hash_initialized) {
361 + srand(time(NULL));
362 + hash_initialized = 1;
363 + }
364 + table->random_seed = rand();
365 +#endif
366 return(table);
367 }
368 xmlFree(table);
369 --- libxml2-2.7.8/parser.c 2010-11-04 16:55:45.000000000 +0100
370 +++ libxml2-2.7.8.patched/parser.c 2012-09-28 12:08:37.440414665 +0200
371 @@ -40,6 +40,7 @@
372 #endif
373
374 #include <stdlib.h>
375 +#include <limits.h>
376 #include <string.h>
377 #include <stdarg.h>
378 #include <libxml/xmlmemory.h>
379 @@ -114,10 +115,10 @@
380 * parser option.
381 */
382 static int
383 -xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size,
384 +xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
385 xmlEntityPtr ent)
386 {
387 - unsigned long consumed = 0;
388 + size_t consumed = 0;
389
390 if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
391 return (0);
392 @@ -2580,15 +2581,17 @@
393
394 /*
395 * Macro used to grow the current buffer.
396 + * buffer##_size is expected to be a size_t
397 + * mem_error: is expected to handle memory allocation failures
398 */
399 #define growBuffer(buffer, n) { \
400 xmlChar *tmp; \
401 - buffer##_size *= 2; \
402 - buffer##_size += n; \
403 - tmp = (xmlChar *) \
404 - xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
405 + size_t new_size = buffer##_size * 2 + n; \
406 + if (new_size < buffer##_size) goto mem_error; \
407 + tmp = (xmlChar *) xmlRealloc(buffer, new_size); \
408 if (tmp == NULL) goto mem_error; \
409 buffer = tmp; \
410 + buffer##_size = new_size; \
411 }
412
413 /**
414 @@ -2614,14 +2617,14 @@
415 xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
416 int what, xmlChar end, xmlChar end2, xmlChar end3) {
417 xmlChar *buffer = NULL;
418 - int buffer_size = 0;
419 + size_t buffer_size = 0;
420 + size_t nbchars = 0;
421
422 xmlChar *current = NULL;
423 xmlChar *rep = NULL;
424 const xmlChar *last;
425 xmlEntityPtr ent;
426 int c,l;
427 - int nbchars = 0;
428
429 if ((ctxt == NULL) || (str == NULL) || (len < 0))
430 return(NULL);
431 @@ -2638,7 +2641,7 @@
432 * allocate a translation buffer.
433 */
434 buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
435 - buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
436 + buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
437 if (buffer == NULL) goto mem_error;
438
439 /*
440 @@ -2658,7 +2661,7 @@
441 if (val != 0) {
442 COPY_BUF(0,buffer,nbchars,val);
443 }
444 - if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
445 + if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
446 growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
447 }
448 } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
449 @@ -2676,7 +2679,7 @@
450 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
451 if (ent->content != NULL) {
452 COPY_BUF(0,buffer,nbchars,ent->content[0]);
453 - if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
454 + if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
455 growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
456 }
457 } else {
458 @@ -2693,8 +2696,7 @@
459 current = rep;
460 while (*current != 0) { /* non input consuming loop */
461 buffer[nbchars++] = *current++;
462 - if (nbchars >
463 - buffer_size - XML_PARSER_BUFFER_SIZE) {
464 + if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
465 if (xmlParserEntityCheck(ctxt, nbchars, ent))
466 goto int_error;
467 growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
468 @@ -2708,8 +2710,8 @@
469 const xmlChar *cur = ent->name;
470
471 buffer[nbchars++] = '&';
472 - if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
473 - growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
474 + if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
475 + growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
476 }
477 for (;i > 0;i--)
478 buffer[nbchars++] = *cur++;
479 @@ -2736,8 +2738,7 @@
480 current = rep;
481 while (*current != 0) { /* non input consuming loop */
482 buffer[nbchars++] = *current++;
483 - if (nbchars >
484 - buffer_size - XML_PARSER_BUFFER_SIZE) {
485 + if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
486 if (xmlParserEntityCheck(ctxt, nbchars, ent))
487 goto int_error;
488 growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
489 @@ -2750,8 +2751,8 @@
490 } else {
491 COPY_BUF(l,buffer,nbchars,c);
492 str += l;
493 - if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
494 - growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
495 + if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
496 + growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
497 }
498 }
499 if (str < last)
500 @@ -3755,8 +3756,8 @@
501 xmlChar limit = 0;
502 xmlChar *buf = NULL;
503 xmlChar *rep = NULL;
504 - int len = 0;
505 - int buf_size = 0;
506 + size_t len = 0;
507 + size_t buf_size = 0;
508 int c, l, in_space = 0;
509 xmlChar *current = NULL;
510 xmlEntityPtr ent;
511 @@ -3778,7 +3779,7 @@
512 * allocate a translation buffer.
513 */
514 buf_size = XML_PARSER_BUFFER_SIZE;
515 - buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar));
516 + buf = (xmlChar *) xmlMallocAtomic(buf_size);
517 if (buf == NULL) goto mem_error;
518
519 /*
520 @@ -3795,7 +3796,7 @@
521
522 if (val == '&') {
523 if (ctxt->replaceEntities) {
524 - if (len > buf_size - 10) {
525 + if (len + 10 > buf_size) {
526 growBuffer(buf, 10);
527 }
528 buf[len++] = '&';
529 @@ -3804,7 +3805,7 @@
530 * The reparsing will be done in xmlStringGetNodeList()
531 * called by the attribute() function in SAX.c
532 */
533 - if (len > buf_size - 10) {
534 + if (len + 10 > buf_size) {
535 growBuffer(buf, 10);
536 }
537 buf[len++] = '&';
538 @@ -3814,7 +3815,7 @@
539 buf[len++] = ';';
540 }
541 } else if (val != 0) {
542 - if (len > buf_size - 10) {
543 + if (len + 10 > buf_size) {
544 growBuffer(buf, 10);
545 }
546 len += xmlCopyChar(0, &buf[len], val);
547 @@ -3826,7 +3827,7 @@
548 ctxt->nbentities += ent->owner;
549 if ((ent != NULL) &&
550 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
551 - if (len > buf_size - 10) {
552 + if (len + 10 > buf_size) {
553 growBuffer(buf, 10);
554 }
555 if ((ctxt->replaceEntities == 0) &&
556 @@ -3854,7 +3855,7 @@
557 current++;
558 } else
559 buf[len++] = *current++;
560 - if (len > buf_size - 10) {
561 + if (len + 10 > buf_size) {
562 growBuffer(buf, 10);
563 }
564 }
565 @@ -3862,7 +3863,7 @@
566 rep = NULL;
567 }
568 } else {
569 - if (len > buf_size - 10) {
570 + if (len + 10 > buf_size) {
571 growBuffer(buf, 10);
572 }
573 if (ent->content != NULL)
574 @@ -3890,7 +3891,7 @@
575 * Just output the reference
576 */
577 buf[len++] = '&';
578 - while (len > buf_size - i - 10) {
579 + while (len + i + 10 > buf_size) {
580 growBuffer(buf, i + 10);
581 }
582 for (;i > 0;i--)
583 @@ -3903,7 +3904,7 @@
584 if ((len != 0) || (!normalize)) {
585 if ((!normalize) || (!in_space)) {
586 COPY_BUF(l,buf,len,0x20);
587 - while (len > buf_size - 10) {
588 + while (len + 10 > buf_size) {
589 growBuffer(buf, 10);
590 }
591 }
592 @@ -3912,7 +3913,7 @@
593 } else {
594 in_space = 0;
595 COPY_BUF(l,buf,len,c);
596 - if (len > buf_size - 10) {
597 + if (len + 10 > buf_size) {
598 growBuffer(buf, 10);
599 }
600 }
601 @@ -3937,7 +3938,18 @@
602 }
603 } else
604 NEXT;
605 - if (attlen != NULL) *attlen = len;
606 +
607 + /*
608 + * There we potentially risk an overflow, don't allow attribute value of
609 + * lenght more than INT_MAX it is a very reasonnable assumption !
610 + */
611 + if (len >= INT_MAX) {
612 + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
613 + "AttValue lenght too long\n");
614 + goto mem_error;
615 + }
616 +
617 + if (attlen != NULL) *attlen = (int) len;
618 return(buf);
619
620 mem_error:
621 @@ -4949,7 +4961,8 @@
622 (ctxt->sax->processingInstruction != NULL))
623 ctxt->sax->processingInstruction(ctxt->userData,
624 target, NULL);
625 - ctxt->instate = state;
626 + if (ctxt->instate != XML_PARSER_EOF)
627 + ctxt->instate = state;
628 return;
629 }
630 buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
631 @@ -5029,7 +5042,8 @@
632 } else {
633 xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
634 }
635 - ctxt->instate = state;
636 + if (ctxt->instate != XML_PARSER_EOF)
637 + ctxt->instate = state;
638 }
639 }
640
641 @@ -9588,6 +9602,8 @@
642 else
643 name = xmlParseStartTag(ctxt);
644 #endif /* LIBXML_SAX1_ENABLED */
645 + if (ctxt->instate == XML_PARSER_EOF)
646 + return;
647 if (name == NULL) {
648 spacePop(ctxt);
649 return;
650 @@ -10967,6 +10983,8 @@
651 else
652 name = xmlParseStartTag(ctxt);
653 #endif /* LIBXML_SAX1_ENABLED */
654 + if (ctxt->instate == XML_PARSER_EOF)
655 + goto done;
656 if (name == NULL) {
657 spacePop(ctxt);
658 ctxt->instate = XML_PARSER_EOF;
659 @@ -11153,7 +11171,9 @@
660 else
661 xmlParseEndTag1(ctxt, 0);
662 #endif /* LIBXML_SAX1_ENABLED */
663 - if (ctxt->nameNr == 0) {
664 + if (ctxt->instate == XML_PARSER_EOF) {
665 + /* Nothing */
666 + } else if (ctxt->nameNr == 0) {
667 ctxt->instate = XML_PARSER_EPILOG;
668 } else {
669 ctxt->instate = XML_PARSER_CONTENT;
670 --- libxml2-2.7.8/xmllint.c 2010-11-03 15:49:11.000000000 +0100
671 +++ libxml2-2.7.8.patched/xmllint.c 2012-09-28 12:08:37.436414665 +0200
672 @@ -2976,7 +2976,7 @@
673 printf("\t--huge : remove any internal arbitrary parser limits\n");
674 printf("\t--noent : substitute entity references by their value\n");
675 printf("\t--noout : don't output the result tree\n");
676 - printf("\t--path 'paths': provide a set of paths for resources\n");
677 + printf("\t--path 'paths' : provide a set of paths for resources\n");
678 printf("\t--load-trace : print trace of all external entites loaded\n");
679 printf("\t--nonet : refuse to fetch DTDs or entities over network\n");
680 printf("\t--nocompact : do not generate compact text nodes\n");
681 @@ -3032,7 +3032,7 @@
682 printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
683 printf("\t otherwise XML Catalogs starting from \n");
684 printf("\t %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
685 - printf("\t--nocatalogs: deactivate all catalogs\n");
686 + printf("\t--nocatalogs : deactivate all catalogs\n");
687 #endif
688 printf("\t--auto : generate a small doc on the fly\n");
689 #ifdef LIBXML_XINCLUDE_ENABLED
690 --- libxml2-2.7.8/xpath.c 2010-11-03 20:18:27.000000000 +0100
691 +++ libxml2-2.7.8.patched/xpath.c 2012-09-28 12:08:37.444414664 +0200
692 @@ -252,6 +252,7 @@
693 "Encoding error\n",
694 "Char out of XML range\n",
695 "Invalid or incomplete context\n",
696 + "Stack usage errror\n",
697 "?? Unknown error ??\n" /* Must be last in the list! */
698 };
699 #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \
700 @@ -2398,6 +2399,42 @@
701 ************************************************************************/
702
703 /**
704 + * xmlXPathSetFrame:
705 + * @ctxt: an XPath parser context
706 + *
707 + * Set the callee evaluation frame
708 + *
709 + * Returns the previous frame value to be restored once done
710 + */
711 +static int
712 +xmlXPathSetFrame(xmlXPathParserContextPtr ctxt) {
713 + int ret;
714 +
715 + if (ctxt == NULL)
716 + return(0);
717 + ret = ctxt->valueFrame;
718 + ctxt->valueFrame = ctxt->valueNr;
719 + return(ret);
720 +}
721 +
722 +/**
723 + * xmlXPathPopFrame:
724 + * @ctxt: an XPath parser context
725 + * @frame: the previous frame value
726 + *
727 + * Remove the callee evaluation frame
728 + */
729 +static void
730 +xmlXPathPopFrame(xmlXPathParserContextPtr ctxt, int frame) {
731 + if (ctxt == NULL)
732 + return;
733 + if (ctxt->valueNr < ctxt->valueFrame) {
734 + xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
735 + }
736 + ctxt->valueFrame = frame;
737 +}
738 +
739 +/**
740 * valuePop:
741 * @ctxt: an XPath evaluation context
742 *
743 @@ -2412,6 +2449,12 @@
744
745 if ((ctxt == NULL) || (ctxt->valueNr <= 0))
746 return (NULL);
747 +
748 + if (ctxt->valueNr <= ctxt->valueFrame) {
749 + xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
750 + return (NULL);
751 + }
752 +
753 ctxt->valueNr--;
754 if (ctxt->valueNr > 0)
755 ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
756 @@ -3522,13 +3565,13 @@
757 } else if (cur->nodeNr == cur->nodeMax) {
758 xmlNodePtr *temp;
759
760 - cur->nodeMax *= 2;
761 - temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
762 + temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
763 sizeof(xmlNodePtr));
764 if (temp == NULL) {
765 xmlXPathErrMemory(NULL, "growing nodeset\n");
766 return;
767 }
768 + cur->nodeMax *= 2;
769 cur->nodeTab = temp;
770 }
771 cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
772 @@ -3627,14 +3670,14 @@
773 } else if (cur->nodeNr == cur->nodeMax) {
774 xmlNodePtr *temp;
775
776 - cur->nodeMax *= 2;
777 - temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
778 + temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
779 sizeof(xmlNodePtr));
780 if (temp == NULL) {
781 xmlXPathErrMemory(NULL, "growing nodeset\n");
782 return;
783 }
784 cur->nodeTab = temp;
785 + cur->nodeMax *= 2;
786 }
787 if (val->type == XML_NAMESPACE_DECL) {
788 xmlNsPtr ns = (xmlNsPtr) val;
789 @@ -3738,14 +3781,14 @@
790 } else if (val1->nodeNr == val1->nodeMax) {
791 xmlNodePtr *temp;
792
793 - val1->nodeMax *= 2;
794 - temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
795 + temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
796 sizeof(xmlNodePtr));
797 if (temp == NULL) {
798 xmlXPathErrMemory(NULL, "merging nodeset\n");
799 return(NULL);
800 }
801 val1->nodeTab = temp;
802 + val1->nodeMax *= 2;
803 }
804 if (n2->type == XML_NAMESPACE_DECL) {
805 xmlNsPtr ns = (xmlNsPtr) n2;
806 @@ -3907,14 +3950,14 @@
807 } else if (set1->nodeNr >= set1->nodeMax) {
808 xmlNodePtr *temp;
809
810 - set1->nodeMax *= 2;
811 temp = (xmlNodePtr *) xmlRealloc(
812 - set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr));
813 + set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
814 if (temp == NULL) {
815 xmlXPathErrMemory(NULL, "merging nodeset\n");
816 return(NULL);
817 }
818 set1->nodeTab = temp;
819 + set1->nodeMax *= 2;
820 }
821 if (n2->type == XML_NAMESPACE_DECL) {
822 xmlNsPtr ns = (xmlNsPtr) n2;
823 @@ -3991,14 +4034,14 @@
824 } else if (set1->nodeNr >= set1->nodeMax) {
825 xmlNodePtr *temp;
826
827 - set1->nodeMax *= 2;
828 temp = (xmlNodePtr *) xmlRealloc(
829 - set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr));
830 + set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
831 if (temp == NULL) {
832 xmlXPathErrMemory(NULL, "merging nodeset\n");
833 return(NULL);
834 }
835 set1->nodeTab = temp;
836 + set1->nodeMax *= 2;
837 }
838 set1->nodeTab[set1->nodeNr++] = n2;
839 }
840 @@ -6154,6 +6197,7 @@
841 ret->valueNr = 0;
842 ret->valueMax = 10;
843 ret->value = NULL;
844 + ret->valueFrame = 0;
845
846 ret->context = ctxt;
847 ret->comp = comp;
848 @@ -11712,6 +11756,7 @@
849 xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
850 xmlNodePtr oldContextNode, contextNode = NULL;
851 xmlXPathContextPtr xpctxt = ctxt->context;
852 + int frame;
853
854 #ifdef LIBXML_XPTR_ENABLED
855 /*
856 @@ -11731,6 +11776,8 @@
857 */
858 exprOp = &ctxt->comp->steps[op->ch2];
859 for (i = 0; i < set->nodeNr; i++) {
860 + xmlXPathObjectPtr tmp;
861 +
862 if (set->nodeTab[i] == NULL)
863 continue;
864
865 @@ -11758,18 +11805,25 @@
866 xmlXPathNodeSetAddUnique(contextObj->nodesetval,
867 contextNode);
868
869 + frame = xmlXPathSetFrame(ctxt);
870 valuePush(ctxt, contextObj);
871 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1);
872 + tmp = valuePop(ctxt);
873 + xmlXPathPopFrame(ctxt, frame);
874
875 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {
876 - xmlXPathObjectPtr tmp;
877 - /* pop the result */
878 - tmp = valuePop(ctxt);
879 - xmlXPathReleaseObject(xpctxt, tmp);
880 - /* then pop off contextObj, which will be freed later */
881 - valuePop(ctxt);
882 + while (tmp != contextObj) {
883 + /*
884 + * Free up the result
885 + * then pop off contextObj, which will be freed later
886 + */
887 + xmlXPathReleaseObject(xpctxt, tmp);
888 + tmp = valuePop(ctxt);
889 + }
890 goto evaluation_error;
891 }
892 + /* push the result back onto the stack */
893 + valuePush(ctxt, tmp);
894
895 if (res)
896 pos++;
897 @@ -13357,6 +13411,7 @@
898 xmlGenericError(xmlGenericErrorContext,
899 "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n",
900 (char *) op->value4, (char *)op->value5);
901 + ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
902 return (total);
903 }
904 val = xmlXPathVariableLookupNS(ctxt->context,
905 @@ -13373,7 +13428,9 @@
906 xmlXPathFunction func;
907 const xmlChar *oldFunc, *oldFuncURI;
908 int i;
909 + int frame;
910
911 + frame = xmlXPathSetFrame(ctxt);
912 if (op->ch1 != -1)
913 total +=
914 xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
915 @@ -13381,15 +13438,18 @@
916 xmlGenericError(xmlGenericErrorContext,
917 "xmlXPathCompOpEval: parameter error\n");
918 ctxt->error = XPATH_INVALID_OPERAND;
919 + xmlXPathPopFrame(ctxt, frame);
920 return (total);
921 }
922 - for (i = 0; i < op->value; i++)
923 + for (i = 0; i < op->value; i++) {
924 if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
925 xmlGenericError(xmlGenericErrorContext,
926 "xmlXPathCompOpEval: parameter error\n");
927 ctxt->error = XPATH_INVALID_OPERAND;
928 + xmlXPathPopFrame(ctxt, frame);
929 return (total);
930 }
931 + }
932 if (op->cache != NULL)
933 XML_CAST_FPTR(func) = op->cache;
934 else {
935 @@ -13405,6 +13465,8 @@
936 xmlGenericError(xmlGenericErrorContext,
937 "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
938 (char *)op->value4, (char *)op->value5);
939 + ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
940 + xmlXPathPopFrame(ctxt, frame);
941 return (total);
942 }
943 func = xmlXPathFunctionLookupNS(ctxt->context,
944 @@ -13426,6 +13488,7 @@
945 func(ctxt, op->value);
946 ctxt->context->function = oldFunc;
947 ctxt->context->functionURI = oldFuncURI;
948 + xmlXPathPopFrame(ctxt, frame);
949 return (total);
950 }
951 case XPATH_OP_ARG:
952 @@ -14329,6 +14392,7 @@
953 ctxt->valueNr = 0;
954 ctxt->valueMax = 10;
955 ctxt->value = NULL;
956 + ctxt->valueFrame = 0;
957 }
958 #ifdef XPATH_STREAMING
959 if (ctxt->comp->stream) {
960 --- libxml2-2.7.8/xpointer.c 2010-10-12 08:25:33.000000000 +0200
961 +++ libxml2-2.7.8.patched/xpointer.c 2012-09-28 12:08:37.428414664 +0200
962 @@ -1007,21 +1007,14 @@
963 NEXT;
964 break;
965 }
966 - *cur++ = CUR;
967 } else if (CUR == '(') {
968 level++;
969 - *cur++ = CUR;
970 } else if (CUR == '^') {
971 - NEXT;
972 - if ((CUR == ')') || (CUR == '(') || (CUR == '^')) {
973 - *cur++ = CUR;
974 - } else {
975 - *cur++ = '^';
976 - *cur++ = CUR;
977 - }
978 - } else {
979 - *cur++ = CUR;
980 + if ((NXT(1) == ')') || (NXT(1) == '(') || (NXT(1) == '^')) {
981 + NEXT;
982 + }
983 }
984 + *cur++ = CUR;
985 NEXT;
986 }
987 *cur = 0;
988 @@ -1269,6 +1262,7 @@
989 ctxt->valueNr = 0;
990 ctxt->valueMax = 10;
991 ctxt->value = NULL;
992 + ctxt->valueFrame = 0;
993 }
994 SKIP_BLANKS;
995 if (CUR == '/') {
996 --- libxml2-2.7.8/libxml.h 2010-10-12 08:25:32.000000000 +0200
997 +++ libxml2-2.7.8.patched/libxml.h 2012-09-28 12:08:37.432414664 +0200
998 @@ -13,6 +13,9 @@
999 #ifndef _LARGEFILE_SOURCE
1000 #define _LARGEFILE_SOURCE
1001 #endif
1002 +#ifndef _LARGEFILE64_SOURCE
1003 +#define _LARGEFILE64_SOURCE
1004 +#endif
1005 #ifndef _FILE_OFFSET_BITS
1006 #define _FILE_OFFSET_BITS 64
1007 #endif
1008 --- libxml2-2.7.8/include/libxml/xpath.h 2010-10-12 08:25:32.000000000 +0200
1009 +++ libxml2-2.7.8.patched/include/libxml/xpath.h 2012-09-28 12:08:37.456414665 +0200
1010 @@ -68,7 +68,8 @@
1011 XPATH_UNDEF_PREFIX_ERROR,
1012 XPATH_ENCODING_ERROR,
1013 XPATH_INVALID_CHAR_ERROR,
1014 - XPATH_INVALID_CTXT
1015 + XPATH_INVALID_CTXT,
1016 + XPATH_STACK_ERROR
1017 } xmlXPathError;
1018
1019 /*
1020 @@ -380,6 +381,8 @@
1021 xmlXPathCompExprPtr comp; /* the precompiled expression */
1022 int xptr; /* it this an XPointer expression */
1023 xmlNodePtr ancestor; /* used for walking preceding axis */
1024 +
1025 + int valueFrame; /* used to limit Pop on the stack */
1026 };
1027
1028 /************************************************************************