--- 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 +#endif +#ifdef HAVE_TIME_H +#include +#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 #ifdef HAVE_STDINT_H #include @@ -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 '' | 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 +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#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 #include #include @@ -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 +#include #include #include #include @@ -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 */ }; /************************************************************************