libxml2: backport Debian patches to fix multiple CVEs
authorFlorian Fainelli <florian@openwrt.org>
Fri, 28 Sep 2012 10:35:14 +0000 (10:35 +0000)
committerFlorian Fainelli <florian@openwrt.org>
Fri, 28 Sep 2012 10:35:14 +0000 (10:35 +0000)
SVN-Revision: 33578

libs/libxml2/Makefile
libs/libxml2/patches/001-debian_CVEs.patch [new file with mode: 0644]

index d837ac3b3c525cf1fa146c23a71bc6e84edf3f12..25e93fd506cdc3114fd41fc326dee0f70cba5af3 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2006-2012 OpenWrt.org
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=libxml2
 PKG_VERSION:=2.7.8
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://gd.tuwien.ac.at/languages/libxml/ \
diff --git a/libs/libxml2/patches/001-debian_CVEs.patch b/libs/libxml2/patches/001-debian_CVEs.patch
new file mode 100644 (file)
index 0000000..6b34bf6
--- /dev/null
@@ -0,0 +1,1028 @@
+--- libxml2-2.7.8/dict.c       2010-10-12 08:25:31.000000000 +0200
++++ libxml2-2.7.8.patched/dict.c       2012-09-28 12:08:37.432414664 +0200
+@@ -2,7 +2,7 @@
+  * dict.c: dictionary of reusable strings, just used to avoid allocation
+  *         and freeing operations.
+  *
+- * Copyright (C) 2003 Daniel Veillard.
++ * Copyright (C) 2003-2012 Daniel Veillard.
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -19,6 +19,28 @@
+ #define IN_LIBXML
+ #include "libxml.h"
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++#ifdef HAVE_TIME_H
++#include <time.h>
++#endif
++
++/*
++ * Following http://www.ocert.org/advisories/ocert-2011-003.html
++ * it seems that having hash randomization might be a good idea
++ * when using XML with untrusted data
++ * Note1: that it works correctly only if compiled with WITH_BIG_KEY
++ *  which is the default.
++ * Note2: the fast function used for a small dict won't protect very
++ *  well but since the attack is based on growing a very big hash
++ *  list we will use the BigKey algo as soon as the hash size grows
++ *  over MIN_DICT_SIZE so this actually works
++ */
++#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME)
++#define DICT_RANDOMIZATION
++#endif
++
+ #include <string.h>
+ #ifdef HAVE_STDINT_H
+ #include <stdint.h>
+@@ -44,23 +66,23 @@
+ #define WITH_BIG_KEY
+ #ifdef WITH_BIG_KEY
+-#define xmlDictComputeKey(dict, name, len)                    \
+-    (((dict)->size == MIN_DICT_SIZE) ?                                \
+-     xmlDictComputeFastKey(name, len) :                               \
+-     xmlDictComputeBigKey(name, len))
+-
+-#define xmlDictComputeQKey(dict, prefix, plen, name, len)     \
+-    (((prefix) == NULL) ?                                     \
+-      (xmlDictComputeKey(dict, name, len)) :                  \
+-      (((dict)->size == MIN_DICT_SIZE) ?                      \
+-       xmlDictComputeFastQKey(prefix, plen, name, len) :      \
+-       xmlDictComputeBigQKey(prefix, plen, name, len)))
++#define xmlDictComputeKey(dict, name, len)                              \
++    (((dict)->size == MIN_DICT_SIZE) ?                                  \
++     xmlDictComputeFastKey(name, len, (dict)->seed) :                   \
++     xmlDictComputeBigKey(name, len, (dict)->seed))
++
++#define xmlDictComputeQKey(dict, prefix, plen, name, len)               \
++    (((prefix) == NULL) ?                                               \
++      (xmlDictComputeKey(dict, name, len)) :                             \
++      (((dict)->size == MIN_DICT_SIZE) ?                                \
++       xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) :        \
++       xmlDictComputeBigQKey(prefix, plen, name, len, (dict)->seed)))
+ #else /* !WITH_BIG_KEY */
+-#define xmlDictComputeKey(dict, name, len)                    \
+-        xmlDictComputeFastKey(name, len)
+-#define xmlDictComputeQKey(dict, prefix, plen, name, len)     \
+-        xmlDictComputeFastQKey(prefix, plen, name, len)
++#define xmlDictComputeKey(dict, name, len)                              \
++        xmlDictComputeFastKey(name, len, (dict)->seed)
++#define xmlDictComputeQKey(dict, prefix, plen, name, len)               \
++        xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed)
+ #endif /* WITH_BIG_KEY */
+ /*
+@@ -98,6 +120,8 @@
+     xmlDictStringsPtr strings;
+     struct _xmlDict *subdict;
++    /* used for randomization */
++    int seed;
+ };
+ /*
+@@ -125,6 +149,9 @@
+     if ((xmlDictMutex = xmlNewRMutex()) == NULL)
+         return(0);
++#ifdef DICT_RANDOMIZATION
++    srand(time(NULL));
++#endif
+     xmlDictInitialized = 1;
+     return(1);
+ }
+@@ -277,13 +304,13 @@
+  */
+ static uint32_t
+-xmlDictComputeBigKey(const xmlChar* data, int namelen) {
++xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
+     uint32_t hash;
+     int i;
+     if (namelen <= 0 || data == NULL) return(0);
+-    hash = 0;
++    hash = seed;
+     for (i = 0;i < namelen; i++) {
+         hash += data[i];
+@@ -310,12 +337,12 @@
+  */
+ static unsigned long
+ xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
+-                      const xmlChar *name, int len)
++                      const xmlChar *name, int len, int seed)
+ {
+     uint32_t hash;
+     int i;
+-    hash = 0;
++    hash = seed;
+     for (i = 0;i < plen; i++) {
+         hash += prefix[i];
+@@ -346,8 +373,8 @@
+  * for low hash table fill.
+  */
+ static unsigned long
+-xmlDictComputeFastKey(const xmlChar *name, int namelen) {
+-    unsigned long value = 0L;
++xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
++    unsigned long value = seed;
+     if (name == NULL) return(0);
+     value = *name;
+@@ -381,9 +408,9 @@
+  */
+ static unsigned long
+ xmlDictComputeFastQKey(const xmlChar *prefix, int plen,
+-                       const xmlChar *name, int len)
++                       const xmlChar *name, int len, int seed)
+ {
+-    unsigned long value = 0L;
++    unsigned long value = (unsigned long) seed;
+     if (plen == 0)
+       value += 30 * (unsigned long) ':';
+@@ -460,6 +487,11 @@
+       dict->subdict = NULL;
+         if (dict->dict) {
+           memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
++#ifdef DICT_RANDOMIZATION
++            dict->seed = rand();
++#else
++            dict->seed = 0;
++#endif
+           return(dict);
+         }
+         xmlFree(dict);
+@@ -486,6 +518,7 @@
+ #ifdef DICT_DEBUG_PATTERNS
+         fprintf(stderr, "R");
+ #endif
++        dict->seed = sub->seed;
+         dict->subdict = sub;
+       xmlDictReference(dict->subdict);
+     }
+--- libxml2-2.7.8/encoding.c   2010-11-04 17:40:06.000000000 +0100
++++ libxml2-2.7.8.patched/encoding.c   2012-09-28 12:08:37.440414665 +0200
+@@ -1928,7 +1928,7 @@
+     if (in == NULL) return(-1);
+     /* calculate space available */
+-    written = out->size - out->use;
++    written = out->size - out->use - 1; /* count '\0' */
+     toconv = in->use;
+     /*
+      * echo '<?xml version="1.0" encoding="UCS4"?>' | wc -c => 38
+@@ -2059,7 +2059,7 @@
+     toconv = in->use;
+     if (toconv == 0)
+         return (0);
+-    written = out->size - out->use;
++    written = out->size - out->use - 1; /* count '\0' */
+     if (toconv * 2 >= written) {
+         xmlBufferGrow(out, out->size + toconv * 2);
+         written = out->size - out->use - 1;
+--- libxml2-2.7.8/entities.c   2010-10-12 08:25:32.000000000 +0200
++++ libxml2-2.7.8.patched/entities.c   2012-09-28 12:08:37.432414664 +0200
+@@ -528,13 +528,13 @@
+  * Macro used to grow the current buffer.
+  */
+ #define growBufferReentrant() {                                               \
+-    buffer_size *= 2;                                                 \
+-    buffer = (xmlChar *)                                              \
+-              xmlRealloc(buffer, buffer_size * sizeof(xmlChar));      \
+-    if (buffer == NULL) {                                             \
+-        xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");\
+-      return(NULL);                                                   \
+-    }                                                                 \
++    xmlChar *tmp;                                                       \
++    size_t new_size = buffer_size * 2;                                  \
++    if (new_size < buffer_size) goto mem_error;                         \
++    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                   \
++    if (tmp == NULL) goto mem_error;                                    \
++    buffer = tmp;                                                     \
++    buffer_size = new_size;                                           \
+ }
+@@ -555,7 +555,7 @@
+     const xmlChar *cur = input;
+     xmlChar *buffer = NULL;
+     xmlChar *out = NULL;
+-    int buffer_size = 0;
++    size_t buffer_size = 0;
+     int html = 0;
+     if (input == NULL) return(NULL);
+@@ -574,8 +574,8 @@
+     out = buffer;
+     while (*cur != '\0') {
+-        if (out - buffer > buffer_size - 100) {
+-          int indx = out - buffer;
++        size_t indx = out - buffer;
++        if (indx + 100 > buffer_size) {
+           growBufferReentrant();
+           out = &buffer[indx];
+@@ -692,6 +692,11 @@
+     }
+     *out = 0;
+     return(buffer);
++
++mem_error:
++    xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");
++    xmlFree(buffer);
++    return(NULL);
+ }
+ /**
+@@ -709,7 +714,7 @@
+     const xmlChar *cur = input;
+     xmlChar *buffer = NULL;
+     xmlChar *out = NULL;
+-    int buffer_size = 0;
++    size_t buffer_size = 0;
+     if (input == NULL) return(NULL);
+     /*
+@@ -724,8 +729,8 @@
+     out = buffer;
+     while (*cur != '\0') {
+-        if (out - buffer > buffer_size - 10) {
+-          int indx = out - buffer;
++        size_t indx = out - buffer;
++        if (indx + 10 > buffer_size) {
+           growBufferReentrant();
+           out = &buffer[indx];
+@@ -774,6 +779,11 @@
+     }
+     *out = 0;
+     return(buffer);
++
++mem_error:
++    xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed");
++    xmlFree(buffer);
++    return(NULL);
+ }
+ /**
+--- libxml2-2.7.8/hash.c       2010-10-12 08:25:32.000000000 +0200
++++ libxml2-2.7.8.patched/hash.c       2012-09-28 12:08:37.392414663 +0200
+@@ -3,7 +3,7 @@
+  *
+  * Reference: Your favorite introductory book on algorithms
+  *
+- * Copyright (C) 2000 Bjorn Reese and Daniel Veillard.
++ * Copyright (C) 2000,2012 Bjorn Reese and Daniel Veillard.
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -21,6 +21,22 @@
+ #include "libxml.h"
+ #include <string.h>
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++#ifdef HAVE_TIME_H
++#include <time.h>
++#endif
++
++/*
++ * Following http://www.ocert.org/advisories/ocert-2011-003.html
++ * it seems that having hash randomization might be a good idea
++ * when using XML with untrusted data
++ */
++#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME)
++#define HASH_RANDOMIZATION
++#endif
++
+ #include <libxml/parser.h>
+ #include <libxml/hash.h>
+ #include <libxml/xmlmemory.h>
+@@ -31,6 +47,10 @@
+ /* #define DEBUG_GROW */
++#ifdef HASH_RANDOMIZATION
++static int hash_initialized = 0;
++#endif
++
+ /*
+  * A single entry in the hash table
+  */
+@@ -53,6 +73,9 @@
+     int size;
+     int nbElems;
+     xmlDictPtr dict;
++#ifdef HASH_RANDOMIZATION
++    int random_seed;
++#endif
+ };
+ /*
+@@ -65,6 +88,9 @@
+     unsigned long value = 0L;
+     char ch;
+     
++#ifdef HASH_RANDOMIZATION
++    value = table->random_seed;
++#endif
+     if (name != NULL) {
+       value += 30 * (*name);
+       while ((ch = *name++) != 0) {
+@@ -92,6 +118,9 @@
+     unsigned long value = 0L;
+     char ch;
+     
++#ifdef HASH_RANDOMIZATION
++    value = table->random_seed;
++#endif
+     if (prefix != NULL)
+       value += 30 * (*prefix);
+     else
+@@ -156,6 +185,13 @@
+         table->table = xmlMalloc(size * sizeof(xmlHashEntry));
+         if (table->table) {
+           memset(table->table, 0, size * sizeof(xmlHashEntry));
++#ifdef HASH_RANDOMIZATION
++            if (!hash_initialized) {
++                srand(time(NULL));
++                hash_initialized = 1;
++            }
++            table->random_seed = rand();
++#endif
+           return(table);
+         }
+         xmlFree(table);
+--- libxml2-2.7.8/parser.c     2010-11-04 16:55:45.000000000 +0100
++++ libxml2-2.7.8.patched/parser.c     2012-09-28 12:08:37.440414665 +0200
+@@ -40,6 +40,7 @@
+ #endif
+ #include <stdlib.h>
++#include <limits.h>
+ #include <string.h>
+ #include <stdarg.h>
+ #include <libxml/xmlmemory.h>
+@@ -114,10 +115,10 @@
+  * parser option.
+  */
+ static int
+-xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size,
++xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
+                      xmlEntityPtr ent)
+ {
+-    unsigned long consumed = 0;
++    size_t consumed = 0;
+     if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
+         return (0);
+@@ -2580,15 +2581,17 @@
+ /*
+  * Macro used to grow the current buffer.
++ * buffer##_size is expected to be a size_t
++ * mem_error: is expected to handle memory allocation failures
+  */
+ #define growBuffer(buffer, n) {                                               \
+     xmlChar *tmp;                                                     \
+-    buffer##_size *= 2;                                                       \
+-    buffer##_size += n;                                                       \
+-    tmp = (xmlChar *)                                                 \
+-              xmlRealloc(buffer, buffer##_size * sizeof(xmlChar));    \
++    size_t new_size = buffer##_size * 2 + n;                            \
++    if (new_size < buffer##_size) goto mem_error;                       \
++    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
+     if (tmp == NULL) goto mem_error;                                  \
+     buffer = tmp;                                                     \
++    buffer##_size = new_size;                                           \
+ }
+ /**
+@@ -2614,14 +2617,14 @@
+ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
+                     int what, xmlChar end, xmlChar  end2, xmlChar end3) {
+     xmlChar *buffer = NULL;
+-    int buffer_size = 0;
++    size_t buffer_size = 0;
++    size_t nbchars = 0;
+     xmlChar *current = NULL;
+     xmlChar *rep = NULL;
+     const xmlChar *last;
+     xmlEntityPtr ent;
+     int c,l;
+-    int nbchars = 0;
+     if ((ctxt == NULL) || (str == NULL) || (len < 0))
+       return(NULL);
+@@ -2638,7 +2641,7 @@
+      * allocate a translation buffer.
+      */
+     buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
+-    buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
++    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
+     if (buffer == NULL) goto mem_error;
+     /*
+@@ -2658,7 +2661,7 @@
+           if (val != 0) {
+               COPY_BUF(0,buffer,nbchars,val);
+           }
+-          if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
++          if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+               growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+           }
+       } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
+@@ -2676,7 +2679,7 @@
+               (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
+               if (ent->content != NULL) {
+                   COPY_BUF(0,buffer,nbchars,ent->content[0]);
+-                  if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
++                  if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+                       growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+                   }
+               } else {
+@@ -2693,8 +2696,7 @@
+                   current = rep;
+                   while (*current != 0) { /* non input consuming loop */
+                       buffer[nbchars++] = *current++;
+-                      if (nbchars >
+-                          buffer_size - XML_PARSER_BUFFER_SIZE) {
++                      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+                           if (xmlParserEntityCheck(ctxt, nbchars, ent))
+                               goto int_error;
+                           growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+@@ -2708,8 +2710,8 @@
+               const xmlChar *cur = ent->name;
+               buffer[nbchars++] = '&';
+-              if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
+-                  growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
++              if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
++                  growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
+               }
+               for (;i > 0;i--)
+                   buffer[nbchars++] = *cur++;
+@@ -2736,8 +2738,7 @@
+                   current = rep;
+                   while (*current != 0) { /* non input consuming loop */
+                       buffer[nbchars++] = *current++;
+-                      if (nbchars >
+-                          buffer_size - XML_PARSER_BUFFER_SIZE) {
++                      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+                           if (xmlParserEntityCheck(ctxt, nbchars, ent))
+                               goto int_error;
+                           growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+@@ -2750,8 +2751,8 @@
+       } else {
+           COPY_BUF(l,buffer,nbchars,c);
+           str += l;
+-          if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
+-            growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
++          if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
++              growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+           }
+       }
+       if (str < last)
+@@ -3755,8 +3756,8 @@
+     xmlChar limit = 0;
+     xmlChar *buf = NULL;
+     xmlChar *rep = NULL;
+-    int len = 0;
+-    int buf_size = 0;
++    size_t len = 0;
++    size_t buf_size = 0;
+     int c, l, in_space = 0;
+     xmlChar *current = NULL;
+     xmlEntityPtr ent;
+@@ -3778,7 +3779,7 @@
+      * allocate a translation buffer.
+      */
+     buf_size = XML_PARSER_BUFFER_SIZE;
+-    buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar));
++    buf = (xmlChar *) xmlMallocAtomic(buf_size);
+     if (buf == NULL) goto mem_error;
+     /*
+@@ -3795,7 +3796,7 @@
+               if (val == '&') {
+                   if (ctxt->replaceEntities) {
+-                      if (len > buf_size - 10) {
++                      if (len + 10 > buf_size) {
+                           growBuffer(buf, 10);
+                       }
+                       buf[len++] = '&';
+@@ -3804,7 +3805,7 @@
+                        * The reparsing will be done in xmlStringGetNodeList()
+                        * called by the attribute() function in SAX.c
+                        */
+-                      if (len > buf_size - 10) {
++                      if (len + 10 > buf_size) {
+                           growBuffer(buf, 10);
+                       }
+                       buf[len++] = '&';
+@@ -3814,7 +3815,7 @@
+                       buf[len++] = ';';
+                   }
+               } else if (val != 0) {
+-                  if (len > buf_size - 10) {
++                  if (len + 10 > buf_size) {
+                       growBuffer(buf, 10);
+                   }
+                   len += xmlCopyChar(0, &buf[len], val);
+@@ -3826,7 +3827,7 @@
+                   ctxt->nbentities += ent->owner;
+               if ((ent != NULL) &&
+                   (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
+-                  if (len > buf_size - 10) {
++                  if (len + 10 > buf_size) {
+                       growBuffer(buf, 10);
+                   }
+                   if ((ctxt->replaceEntities == 0) &&
+@@ -3854,7 +3855,7 @@
+                                     current++;
+                                 } else
+                                     buf[len++] = *current++;
+-                              if (len > buf_size - 10) {
++                              if (len + 10 > buf_size) {
+                                   growBuffer(buf, 10);
+                               }
+                           }
+@@ -3862,7 +3863,7 @@
+                           rep = NULL;
+                       }
+                   } else {
+-                      if (len > buf_size - 10) {
++                      if (len + 10 > buf_size) {
+                           growBuffer(buf, 10);
+                       }
+                       if (ent->content != NULL)
+@@ -3890,7 +3891,7 @@
+                    * Just output the reference
+                    */
+                   buf[len++] = '&';
+-                  while (len > buf_size - i - 10) {
++                  while (len + i + 10 > buf_size) {
+                       growBuffer(buf, i + 10);
+                   }
+                   for (;i > 0;i--)
+@@ -3903,7 +3904,7 @@
+               if ((len != 0) || (!normalize)) {
+                   if ((!normalize) || (!in_space)) {
+                       COPY_BUF(l,buf,len,0x20);
+-                      while (len > buf_size - 10) {
++                      while (len + 10 > buf_size) {
+                           growBuffer(buf, 10);
+                       }
+                   }
+@@ -3912,7 +3913,7 @@
+           } else {
+               in_space = 0;
+               COPY_BUF(l,buf,len,c);
+-              if (len > buf_size - 10) {
++              if (len + 10 > buf_size) {
+                   growBuffer(buf, 10);
+               }
+           }
+@@ -3937,7 +3938,18 @@
+         }
+     } else
+       NEXT;
+-    if (attlen != NULL) *attlen = len;
++
++    /*
++     * There we potentially risk an overflow, don't allow attribute value of
++     * lenght more than INT_MAX it is a very reasonnable assumption !
++     */
++    if (len >= INT_MAX) {
++        xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
++                       "AttValue lenght too long\n");
++        goto mem_error;
++    }
++
++    if (attlen != NULL) *attlen = (int) len;
+     return(buf);
+ mem_error:
+@@ -4949,7 +4961,8 @@
+                   (ctxt->sax->processingInstruction != NULL))
+                   ctxt->sax->processingInstruction(ctxt->userData,
+                                                    target, NULL);
+-              ctxt->instate = state;
++              if (ctxt->instate != XML_PARSER_EOF)
++                  ctxt->instate = state;
+               return;
+           }
+           buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+@@ -5029,7 +5042,8 @@
+       } else {
+           xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
+       }
+-      ctxt->instate = state;
++      if (ctxt->instate != XML_PARSER_EOF)
++          ctxt->instate = state;
+     }
+ }
+@@ -9588,6 +9602,8 @@
+     else
+       name = xmlParseStartTag(ctxt);
+ #endif /* LIBXML_SAX1_ENABLED */
++    if (ctxt->instate == XML_PARSER_EOF)
++      return;
+     if (name == NULL) {
+       spacePop(ctxt);
+         return;
+@@ -10967,6 +10983,8 @@
+               else
+                   name = xmlParseStartTag(ctxt);
+ #endif /* LIBXML_SAX1_ENABLED */
++              if (ctxt->instate == XML_PARSER_EOF)
++                  goto done;
+               if (name == NULL) {
+                   spacePop(ctxt);
+                   ctxt->instate = XML_PARSER_EOF;
+@@ -11153,7 +11171,9 @@
+                 else
+                   xmlParseEndTag1(ctxt, 0);
+ #endif /* LIBXML_SAX1_ENABLED */
+-              if (ctxt->nameNr == 0) {
++              if (ctxt->instate == XML_PARSER_EOF) {
++                  /* Nothing */
++              } else if (ctxt->nameNr == 0) {
+                   ctxt->instate = XML_PARSER_EPILOG;
+               } else {
+                   ctxt->instate = XML_PARSER_CONTENT;
+--- libxml2-2.7.8/xmllint.c    2010-11-03 15:49:11.000000000 +0100
++++ libxml2-2.7.8.patched/xmllint.c    2012-09-28 12:08:37.436414665 +0200
+@@ -2976,7 +2976,7 @@
+     printf("\t--huge : remove any internal arbitrary parser limits\n");
+     printf("\t--noent : substitute entity references by their value\n");
+     printf("\t--noout : don't output the result tree\n");
+-    printf("\t--path 'paths': provide a set of paths for resources\n");
++    printf("\t--path 'paths' : provide a set of paths for resources\n");
+     printf("\t--load-trace : print trace of all external entites loaded\n");
+     printf("\t--nonet : refuse to fetch DTDs or entities over network\n");
+     printf("\t--nocompact : do not generate compact text nodes\n");
+@@ -3032,7 +3032,7 @@
+     printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
+     printf("\t             otherwise XML Catalogs starting from \n");
+     printf("\t         %s are activated by default\n", XML_XML_DEFAULT_CATALOG);
+-    printf("\t--nocatalogs: deactivate all catalogs\n");
++    printf("\t--nocatalogs : deactivate all catalogs\n");
+ #endif
+     printf("\t--auto : generate a small doc on the fly\n");
+ #ifdef LIBXML_XINCLUDE_ENABLED
+--- libxml2-2.7.8/xpath.c      2010-11-03 20:18:27.000000000 +0100
++++ libxml2-2.7.8.patched/xpath.c      2012-09-28 12:08:37.444414664 +0200
+@@ -252,6 +252,7 @@
+     "Encoding error\n",
+     "Char out of XML range\n",
+     "Invalid or incomplete context\n",
++    "Stack usage errror\n",
+     "?? Unknown error ??\n"   /* Must be last in the list! */
+ };
+ #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) /       \
+@@ -2398,6 +2399,42 @@
+  ************************************************************************/
+ /**
++ * xmlXPathSetFrame:
++ * @ctxt: an XPath parser context
++ *
++ * Set the callee evaluation frame
++ *
++ * Returns the previous frame value to be restored once done
++ */
++static int
++xmlXPathSetFrame(xmlXPathParserContextPtr ctxt) {
++    int ret;
++
++    if (ctxt == NULL)
++        return(0);
++    ret = ctxt->valueFrame;
++    ctxt->valueFrame = ctxt->valueNr;
++    return(ret);
++}
++
++/**
++ * xmlXPathPopFrame:
++ * @ctxt: an XPath parser context
++ * @frame: the previous frame value
++ *
++ * Remove the callee evaluation frame
++ */
++static void
++xmlXPathPopFrame(xmlXPathParserContextPtr ctxt, int frame) {
++    if (ctxt == NULL)
++        return;
++    if (ctxt->valueNr < ctxt->valueFrame) {
++        xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
++    }
++    ctxt->valueFrame = frame;
++}
++
++/**
+  * valuePop:
+  * @ctxt: an XPath evaluation context
+  *
+@@ -2412,6 +2449,12 @@
+     if ((ctxt == NULL) || (ctxt->valueNr <= 0))
+         return (NULL);
++
++    if (ctxt->valueNr <= ctxt->valueFrame) {
++        xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
++        return (NULL);
++    }
++
+     ctxt->valueNr--;
+     if (ctxt->valueNr > 0)
+         ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
+@@ -3522,13 +3565,13 @@
+     } else if (cur->nodeNr == cur->nodeMax) {
+         xmlNodePtr *temp;
+-        cur->nodeMax *= 2;
+-      temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
++      temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
+                                     sizeof(xmlNodePtr));
+       if (temp == NULL) {
+           xmlXPathErrMemory(NULL, "growing nodeset\n");
+           return;
+       }
++        cur->nodeMax *= 2;
+       cur->nodeTab = temp;
+     }
+     cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
+@@ -3627,14 +3670,14 @@
+     } else if (cur->nodeNr == cur->nodeMax) {
+         xmlNodePtr *temp;
+-        cur->nodeMax *= 2;
+-      temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
++      temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
+                                     sizeof(xmlNodePtr));
+       if (temp == NULL) {
+           xmlXPathErrMemory(NULL, "growing nodeset\n");
+           return;
+       }
+       cur->nodeTab = temp;
++        cur->nodeMax *= 2;
+     }
+     if (val->type == XML_NAMESPACE_DECL) {
+       xmlNsPtr ns = (xmlNsPtr) val;
+@@ -3738,14 +3781,14 @@
+       } else if (val1->nodeNr == val1->nodeMax) {
+           xmlNodePtr *temp;
+-          val1->nodeMax *= 2;
+-          temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
++          temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
+                                            sizeof(xmlNodePtr));
+           if (temp == NULL) {
+               xmlXPathErrMemory(NULL, "merging nodeset\n");
+               return(NULL);
+           }
+           val1->nodeTab = temp;
++          val1->nodeMax *= 2;
+       }
+       if (n2->type == XML_NAMESPACE_DECL) {
+           xmlNsPtr ns = (xmlNsPtr) n2;
+@@ -3907,14 +3950,14 @@
+           } else if (set1->nodeNr >= set1->nodeMax) {
+               xmlNodePtr *temp;
+-              set1->nodeMax *= 2;
+               temp = (xmlNodePtr *) xmlRealloc(
+-                  set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr));
++                  set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
+               if (temp == NULL) {
+                   xmlXPathErrMemory(NULL, "merging nodeset\n");
+                   return(NULL);
+               }
+               set1->nodeTab = temp;
++              set1->nodeMax *= 2;
+           }
+           if (n2->type == XML_NAMESPACE_DECL) {
+               xmlNsPtr ns = (xmlNsPtr) n2;
+@@ -3991,14 +4034,14 @@
+           } else if (set1->nodeNr >= set1->nodeMax) {
+               xmlNodePtr *temp;
+-              set1->nodeMax *= 2;
+               temp = (xmlNodePtr *) xmlRealloc(
+-                  set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr));
++                  set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
+               if (temp == NULL) {
+                   xmlXPathErrMemory(NULL, "merging nodeset\n");
+                   return(NULL);
+               }
+               set1->nodeTab = temp;
++              set1->nodeMax *= 2;
+           }
+           set1->nodeTab[set1->nodeNr++] = n2;
+       }
+@@ -6154,6 +6197,7 @@
+     ret->valueNr = 0;
+     ret->valueMax = 10;
+     ret->value = NULL;
++    ret->valueFrame = 0;
+     ret->context = ctxt;
+     ret->comp = comp;
+@@ -11712,6 +11756,7 @@
+       xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
+       xmlNodePtr oldContextNode, contextNode = NULL;
+       xmlXPathContextPtr xpctxt = ctxt->context;
++      int frame;
+ #ifdef LIBXML_XPTR_ENABLED
+           /*
+@@ -11731,6 +11776,8 @@
+       */
+       exprOp = &ctxt->comp->steps[op->ch2];
+       for (i = 0; i < set->nodeNr; i++) {
++          xmlXPathObjectPtr tmp;
++
+           if (set->nodeTab[i] == NULL)
+               continue;
+@@ -11758,18 +11805,25 @@
+               xmlXPathNodeSetAddUnique(contextObj->nodesetval,
+                   contextNode);
++          frame = xmlXPathSetFrame(ctxt);
+           valuePush(ctxt, contextObj);
+           res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1);
++          tmp = valuePop(ctxt);
++          xmlXPathPopFrame(ctxt, frame);
+           if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {
+-              xmlXPathObjectPtr tmp;
+-              /* pop the result */
+-              tmp = valuePop(ctxt);
+-              xmlXPathReleaseObject(xpctxt, tmp);
+-              /* then pop off contextObj, which will be freed later */
+-              valuePop(ctxt);
++              while (tmp != contextObj) {
++                    /*
++                     * Free up the result
++                     * then pop off contextObj, which will be freed later
++                     */
++                    xmlXPathReleaseObject(xpctxt, tmp);
++                  tmp = valuePop(ctxt);
++                }
+               goto evaluation_error;
+           }
++            /* push the result back onto the stack */
++            valuePush(ctxt, tmp);
+           if (res)
+               pos++;
+@@ -13357,6 +13411,7 @@
+                         xmlGenericError(xmlGenericErrorContext,
+             "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n",
+                                     (char *) op->value4, (char *)op->value5);
++                      ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
+                         return (total);
+                     }
+                   val = xmlXPathVariableLookupNS(ctxt->context,
+@@ -13373,7 +13428,9 @@
+                 xmlXPathFunction func;
+                 const xmlChar *oldFunc, *oldFuncURI;
+               int i;
++              int frame;
++              frame = xmlXPathSetFrame(ctxt);
+                 if (op->ch1 != -1)
+                     total +=
+                         xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
+@@ -13381,15 +13438,18 @@
+                   xmlGenericError(xmlGenericErrorContext,
+                           "xmlXPathCompOpEval: parameter error\n");
+                   ctxt->error = XPATH_INVALID_OPERAND;
++                  xmlXPathPopFrame(ctxt, frame);
+                   return (total);
+               }
+-              for (i = 0; i < op->value; i++)
++              for (i = 0; i < op->value; i++) {
+                   if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
+                       xmlGenericError(xmlGenericErrorContext,
+                               "xmlXPathCompOpEval: parameter error\n");
+                       ctxt->error = XPATH_INVALID_OPERAND;
++                      xmlXPathPopFrame(ctxt, frame);
+                       return (total);
+                   }
++              }
+                 if (op->cache != NULL)
+                     XML_CAST_FPTR(func) = op->cache;
+                 else {
+@@ -13405,6 +13465,8 @@
+                             xmlGenericError(xmlGenericErrorContext,
+             "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
+                                     (char *)op->value4, (char *)op->value5);
++                          ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
++                          xmlXPathPopFrame(ctxt, frame);
+                             return (total);
+                         }
+                         func = xmlXPathFunctionLookupNS(ctxt->context,
+@@ -13426,6 +13488,7 @@
+                 func(ctxt, op->value);
+                 ctxt->context->function = oldFunc;
+                 ctxt->context->functionURI = oldFuncURI;
++              xmlXPathPopFrame(ctxt, frame);
+                 return (total);
+             }
+         case XPATH_OP_ARG:
+@@ -14329,6 +14392,7 @@
+       ctxt->valueNr = 0;
+       ctxt->valueMax = 10;
+       ctxt->value = NULL;
++      ctxt->valueFrame = 0;
+     }
+ #ifdef XPATH_STREAMING
+     if (ctxt->comp->stream) {
+--- libxml2-2.7.8/xpointer.c   2010-10-12 08:25:33.000000000 +0200
++++ libxml2-2.7.8.patched/xpointer.c   2012-09-28 12:08:37.428414664 +0200
+@@ -1007,21 +1007,14 @@
+               NEXT;
+               break;
+           }
+-          *cur++ = CUR;
+       } else if (CUR == '(') {
+           level++;
+-          *cur++ = CUR;
+       } else if (CUR == '^') {
+-          NEXT;
+-          if ((CUR == ')') || (CUR == '(') || (CUR == '^')) {
+-              *cur++ = CUR;
+-          } else {
+-              *cur++ = '^';
+-              *cur++ = CUR;
+-          }
+-      } else {
+-          *cur++ = CUR;
++            if ((NXT(1) == ')') || (NXT(1) == '(') || (NXT(1) == '^')) {
++                NEXT;
++            }
+       }
++        *cur++ = CUR;
+       NEXT;
+     }
+     *cur = 0;
+@@ -1269,6 +1262,7 @@
+       ctxt->valueNr = 0;
+       ctxt->valueMax = 10;
+       ctxt->value = NULL;
++      ctxt->valueFrame = 0;
+     }
+     SKIP_BLANKS;
+     if (CUR == '/') {
+--- libxml2-2.7.8/libxml.h     2010-10-12 08:25:32.000000000 +0200
++++ libxml2-2.7.8.patched/libxml.h     2012-09-28 12:08:37.432414664 +0200
+@@ -13,6 +13,9 @@
+ #ifndef _LARGEFILE_SOURCE
+ #define _LARGEFILE_SOURCE
+ #endif
++#ifndef _LARGEFILE64_SOURCE
++#define _LARGEFILE64_SOURCE
++#endif
+ #ifndef _FILE_OFFSET_BITS
+ #define _FILE_OFFSET_BITS 64
+ #endif
+--- libxml2-2.7.8/include/libxml/xpath.h       2010-10-12 08:25:32.000000000 +0200
++++ libxml2-2.7.8.patched/include/libxml/xpath.h       2012-09-28 12:08:37.456414665 +0200
+@@ -68,7 +68,8 @@
+     XPATH_UNDEF_PREFIX_ERROR,
+     XPATH_ENCODING_ERROR,
+     XPATH_INVALID_CHAR_ERROR,
+-    XPATH_INVALID_CTXT
++    XPATH_INVALID_CTXT,
++    XPATH_STACK_ERROR
+ } xmlXPathError;
+ /*
+@@ -380,6 +381,8 @@
+     xmlXPathCompExprPtr comp;         /* the precompiled expression */
+     int xptr;                         /* it this an XPointer expression */
+     xmlNodePtr         ancestor;      /* used for walking preceding axis */
++
++    int              valueFrame;        /* used to limit Pop on the stack */
+ };
+ /************************************************************************