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 /************************************************************************
1029