[libxml2/f17] Accumulated fixes for various security errata + a few bug fixes
Daniel Veillard
veillard at fedoraproject.org
Mon Sep 10 05:41:51 UTC 2012
commit 4e98652b8701a7f6ccb59484210930abf5ab9544
Author: Daniel Veillard <veillard at redhat.com>
Date: Mon Sep 10 13:40:16 2012 +0800
Accumulated fixes for various security errata + a few bug fixes
- Fixes for CVE-2011-3919 CVE-2011-3905 CVE-2011-2834 (rhbz#772122)
- Fixes for CVE-2012-2807 (843743)
- Fixes for CVE-2012-0841 (795698)
- Fix for CVE-2011-1944 (709750)
- Fix for CVE-2011-0216 (755813)
- Fix for CVE-2011-2821 (735715)
- Fix for CVE-2011-3102 (822171)
Daniel
libxml2-2.7.7-xpath-double-free.patch | 22 -
libxml2-2.7.8-reactivate-versionning-script.patch | 58 ---
...randomization-to-hash-and-dict-structures.patch | 300 +++++++++++
...atic-behaviour-in-some-push-parsing-cases.patch | 247 ++++++++++
...XPath-code-to-percolate-allocation-errors.patch | 484 ++++++++++++++++++
...anups-and-new-limit-APIs-for-dictionaries.patch | 519 ++++++++++++++++++++
...ml2-Do-not-fetch-external-parsed-entities.patch | 71 +++
...SER_EOF-state-handling-through-the-parser.patch | 481 ++++++++++++++++++
...lure-to-report-xmlreader-parsing-failures.patch | 37 ++
...l2-Fix-a-potential-freeing-error-in-XPath.patch | 38 ++
...gfault-on-XSD-validation-on-pattern-error.patch | 56 +++
...an-allocation-error-when-copying-entities.patch | 27 +
libxml2-Fix-an-error-in-previous-commit.patch | 27 +
libxml2-Fix-an-off-by-one-error-in-encoding.patch | 39 ++
libxml2-Fix-an-off-by-one-pointer-access.patch | 46 ++
...nimplemented-part-in-RNG-value-validation.patch | 67 +++
...-Fix-entities-local-buffers-size-problems.patch | 103 ++++
...-missing-error-status-in-XPath-evaluation.patch | 69 +++
...l2-Fix-parser-local-buffers-size-problems.patch | 269 ++++++++++
...tential-problems-on-reallocation-failures.patch | 108 ++++
libxml2-Fixup-limits-parser.patch | 26 +
libxml2-Hardening-of-XPath-evaluation.patch | 233 +++++++++
...t-some-default-limits-in-the-XPath-module.patch | 328 ++++++++++++
libxml2-Impose-a-reasonable-limit-on-PI-size.patch | 82 +++
...pose-a-reasonable-limit-on-attribute-size.patch | 110 ++++
...Impose-a-reasonable-limit-on-comment-size.patch | 97 ++++
libxml2-Introduce-some-default-parser-limits.patch | 310 ++++++++++++
...-parser-returns-when-getting-a-Stop-order.patch | 69 +++
libxml2-More-avoid-quadratic-behaviour.patch | 102 ++++
...-More-fixups-on-the-push-parser-behaviour.patch | 62 +++
libxml2-Multilib-fix.patch | 34 ++
...ate-the-shared-library-versionning-script.patch | 27 +
libxml2-Small-fix-for-previous-commit.patch | 34 ++
...the-push-parser-in-problematic-situations.patch | 71 +++
libxml2-force-randomization-of-dict-and-hash.patch | 45 ++
libxml2-multilib.patch | 24 -
libxml2.spec | 107 ++++-
37 files changed, 4721 insertions(+), 108 deletions(-)
---
diff --git a/libxml2-Add-hash-randomization-to-hash-and-dict-structures.patch b/libxml2-Add-hash-randomization-to-hash-and-dict-structures.patch
new file mode 100644
index 0000000..2a9f380
--- /dev/null
+++ b/libxml2-Add-hash-randomization-to-hash-and-dict-structures.patch
@@ -0,0 +1,300 @@
+From 97de04bc2b75d98a0d8c08f5a757b209d36812ed Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Sat, 4 Feb 2012 19:07:44 +0800
+Subject: [PATCH] Add hash randomization to hash and dict structures
+To: libvir-list at redhat.com
+
+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
+* configure.in: lookup for rand, srand and time
+* dict.c: add randomization to dictionaries hash tables
+* hash.c: add randomization to normal hash tables
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ configure.in | 1 +
+ dict.c | 81 ++++++++++++++++++++++++++++++++++++++++++------------------
+ hash.c | 38 +++++++++++++++++++++++++++-
+ 3 files changed, 95 insertions(+), 25 deletions(-)
+
+diff --git a/configure.in b/configure.in
+index a1d2c89..d35c2e0 100644
+--- a/configure.in
++++ b/configure.in
+@@ -475,6 +475,7 @@ AC_CHECK_FUNCS(strdup strndup strerror)
+ AC_CHECK_FUNCS(finite isnand fp_class class fpclass)
+ AC_CHECK_FUNCS(strftime localtime gettimeofday ftime)
+ AC_CHECK_FUNCS(stat _stat signal)
++AC_CHECK_FUNCS(rand srand time)
+
+ dnl Checking the standard string functions availability
+ AC_CHECK_FUNCS(printf sprintf fprintf snprintf vfprintf vsprintf vsnprintf sscanf,,
+diff --git a/dict.c b/dict.c
+index 3eff231..d73d230 100644
+--- a/dict.c
++++ b/dict.c
+@@ -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_STDLIB_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 @@ typedef unsigned __int32 uint32_t;
+ #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 @@ struct _xmlDict {
+ xmlDictStringsPtr strings;
+
+ struct _xmlDict *subdict;
++ /* used for randomization */
++ int seed;
+ };
+
+ /*
+@@ -125,6 +149,9 @@ static int xmlInitializeDict(void) {
+ if ((xmlDictMutex = xmlNewRMutex()) == NULL)
+ return(0);
+
++#ifdef DICT_RANDOMIZATION
++ srand(time(NULL));
++#endif
+ xmlDictInitialized = 1;
+ return(1);
+ }
+@@ -277,13 +304,13 @@ found_pool:
+ */
+
+ 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 @@ xmlDictComputeBigKey(const xmlChar* data, int namelen) {
+ */
+ 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 @@ xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
+ * 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 @@ xmlDictComputeFastKey(const xmlChar *name, int namelen) {
+ */
+ 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 @@ xmlDictCreate(void) {
+ 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 @@ xmlDictCreateSub(xmlDictPtr sub) {
+ #ifdef DICT_DEBUG_PATTERNS
+ fprintf(stderr, "R");
+ #endif
++ dict->seed = sub->seed;
+ dict->subdict = sub;
+ xmlDictReference(dict->subdict);
+ }
+diff --git a/hash.c b/hash.c
+index b78bc2d..02e01fb 100644
+--- a/hash.c
++++ b/hash.c
+@@ -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_STDLIB_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 @@ struct _xmlHashTable {
+ int size;
+ int nbElems;
+ xmlDictPtr dict;
++#ifdef HASH_RANDOMIZATION
++ int random_seed;
++#endif
+ };
+
+ /*
+@@ -65,6 +88,9 @@ xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
+ 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 @@ xmlHashComputeQKey(xmlHashTablePtr table,
+ 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 @@ xmlHashCreate(int size) {
+ 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);
+--
+1.7.11.4
+
diff --git a/libxml2-Avoid-quadratic-behaviour-in-some-push-parsing-cases.patch b/libxml2-Avoid-quadratic-behaviour-in-some-push-parsing-cases.patch
new file mode 100644
index 0000000..b65f533
--- /dev/null
+++ b/libxml2-Avoid-quadratic-behaviour-in-some-push-parsing-cases.patch
@@ -0,0 +1,247 @@
+From de7893b8e2d73cb9512da7cb7f142d3c31dbbfb5 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Thu, 19 Jul 2012 18:25:01 +0800
+Subject: [PATCH] Avoid quadratic behaviour in some push parsing cases
+To: libvir-list at redhat.com
+
+avoid rescanning over and over a very long input, just check
+the incoming chunks
+
+Conflicts:
+ parser.c: needed some massaging to apply on 2.7.6
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 74 insertions(+), 17 deletions(-)
+
+diff --git a/parser.c b/parser.c
+index 78ae09b..0bb4591 100644
+--- a/parser.c
++++ b/parser.c
+@@ -7303,8 +7303,6 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
+ * Seems we are generating the DOM content, do
+ * a simple tree copy for all references except the first
+ * In the first occurrence list contains the replacement.
+- * progressive == 2 means we are operating on the Reader
+- * and since nodes are discarded we must copy all the time.
+ */
+ if (((list == NULL) && (ent->owner == 0)) ||
+ (ctxt->parseMode == XML_PARSE_READER)) {
+@@ -11283,6 +11281,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ } else {
+ ctxt->instate = XML_PARSER_CONTENT;
+ }
++ ctxt->progressive = 1;
+ break;
+ }
+ if (RAW == '>') {
+@@ -11302,6 +11301,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ #endif /* LIBXML_SAX1_ENABLED */
+
+ ctxt->instate = XML_PARSER_CONTENT;
++ ctxt->progressive = 1;
+ break;
+ }
+ case XML_PARSER_CONTENT: {
+@@ -11335,10 +11335,13 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ ctxt->input->cur += 4;
+ term = xmlParseLookupSequence(ctxt, '-', '-', '>');
+ ctxt->input->cur -= 4;
+- if ((!terminate) && (term < 0))
++ if ((!terminate) && (term < 0)) {
++ ctxt->progressive = XML_PARSER_COMMENT;
+ goto done;
++ }
+ xmlParseComment(ctxt);
+ ctxt->instate = XML_PARSER_CONTENT;
++ ctxt->progressive = 1;
+ } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
+ (ctxt->input->cur[2] == '[') &&
+ (ctxt->input->cur[3] == 'C') &&
+@@ -11529,14 +11532,17 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ (ctxt->input->cur[2] == '-') &&
+ (ctxt->input->cur[3] == '-')) {
+ if ((!terminate) &&
+- (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
++ (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
++ ctxt->progressive = XML_PARSER_COMMENT;
+ goto done;
++ }
+ #ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing Comment\n");
+ #endif
+ xmlParseComment(ctxt);
+ ctxt->instate = XML_PARSER_MISC;
++ ctxt->progressive = 1;
+ ctxt->checkIndex = 0;
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == 'D') &&
+@@ -11584,7 +11590,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ goto done;
+ } else {
+ ctxt->instate = XML_PARSER_START_TAG;
+- ctxt->progressive = 1;
++ ctxt->progressive = XML_PARSER_START_TAG;
+ xmlParseGetLasts(ctxt, &lastlt, &lastgt);
+ #ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+@@ -11614,21 +11620,24 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
+ if ((!terminate) &&
+- (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
++ (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
++ ctxt->progressive = XML_PARSER_COMMENT;
+ goto done;
++ }
+ #ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing Comment\n");
+ #endif
+ xmlParseComment(ctxt);
+ ctxt->instate = XML_PARSER_PROLOG;
++ ctxt->progressive = 1;
+ } else if ((cur == '<') && (next == '!') &&
+ (avail < 4)) {
+ goto done;
+ } else {
+ ctxt->instate = XML_PARSER_START_TAG;
+ if (ctxt->progressive == 0)
+- ctxt->progressive = 1;
++ ctxt->progressive = XML_PARSER_START_TAG;
+ xmlParseGetLasts(ctxt, &lastlt, &lastgt);
+ #ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+@@ -11659,14 +11668,17 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
+ if ((!terminate) &&
+- (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
++ (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
++ ctxt->progressive = XML_PARSER_COMMENT;
+ goto done;
++ }
+ #ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing Comment\n");
+ #endif
+ xmlParseComment(ctxt);
+ ctxt->instate = XML_PARSER_EPILOG;
++ ctxt->progressive = 1;
+ } else if ((cur == '<') && (next == '!') &&
+ (avail < 4)) {
+ goto done;
+@@ -11903,6 +11915,34 @@ encoding_error:
+ }
+
+ /**
++ * xmlParseCheckTransition:
++ * @ctxt: an XML parser context
++ * @chunk: a char array
++ * @size: the size in byte of the chunk
++ *
++ * Check depending on the current parser state if the chunk given must be
++ * processed immediately or one need more data to advance on parsing.
++ *
++ * Returns -1 in case of error, 0 if the push is not needed and 1 if needed
++ */
++static int
++xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
++ if ((ctxt == NULL) || (chunk == NULL) || (size < 0))
++ return(-1);
++ if (ctxt->instate == XML_PARSER_START_TAG) {
++ if (memchr(chunk, '>', size) != NULL)
++ return(1);
++ return(0);
++ }
++ if (ctxt->progressive == XML_PARSER_COMMENT) {
++ if (memchr(chunk, '>', size) != NULL)
++ return(1);
++ return(0);
++ }
++ return(1);
++}
++
++/**
+ * xmlParseChunk:
+ * @ctxt: an XML parser context
+ * @chunk: an char array
+@@ -11918,6 +11958,8 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
+ int terminate) {
+ int end_in_lf = 0;
+ int remain = 0;
++ size_t old_avail = 0;
++ size_t avail = 0;
+
+ if (ctxt == NULL)
+ return(XML_ERR_INTERNAL_ERROR);
+@@ -11941,6 +11983,7 @@ xmldecl_done:
+ int cur = ctxt->input->cur - ctxt->input->base;
+ int res;
+
++ old_avail = ctxt->input->buf->buffer->use;
+ /*
+ * Specific handling if we autodetected an encoding, we should not
+ * push more than the first line ... which depend on the encoding
+@@ -12007,10 +12050,24 @@ xmldecl_done:
+ }
+ }
+ }
+- if (remain != 0)
++ if (remain != 0) {
+ xmlParseTryOrFinish(ctxt, 0);
+- else
+- xmlParseTryOrFinish(ctxt, terminate);
++ } else {
++ if ((ctxt->input != NULL) && (ctxt->input->buf != NULL))
++ avail = ctxt->input->buf->buffer->use;
++ /*
++ * Depending on the current state it may not be such
++ * a good idea to try parsing if there is nothing in the chunk
++ * which would be worth doing a parser state transition and we
++ * need to wait for more data
++ */
++ if ((terminate) || (avail > XML_MAX_TEXT_LENGTH) ||
++ (old_avail == 0) || (avail == 0) ||
++ (xmlParseCheckTransition(ctxt,
++ (const char *)&ctxt->input->base[old_avail],
++ avail - old_avail)))
++ xmlParseTryOrFinish(ctxt, terminate);
++ }
+ if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+ return(ctxt->errNo);
+
+@@ -12028,22 +12085,22 @@ xmldecl_done:
+ /*
+ * Check for termination
+ */
+- int avail = 0;
++ int cur_avail = 0;
+
+ if (ctxt->input != NULL) {
+ if (ctxt->input->buf == NULL)
+- avail = ctxt->input->length -
+- (ctxt->input->cur - ctxt->input->base);
++ cur_avail = ctxt->input->length -
++ (ctxt->input->cur - ctxt->input->base);
+ else
+- avail = ctxt->input->buf->buffer->use -
++ cur_avail = ctxt->input->buf->buffer->use -
+ (ctxt->input->cur - ctxt->input->base);
+ }
+
+ if ((ctxt->instate != XML_PARSER_EOF) &&
+ (ctxt->instate != XML_PARSER_EPILOG)) {
+ xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
+- }
+- if ((ctxt->instate == XML_PARSER_EPILOG) && (avail > 0)) {
++ }
++ if ((ctxt->instate == XML_PARSER_EPILOG) && (cur_avail > 0)) {
+ xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
+ }
+ if (ctxt->instate != XML_PARSER_EOF) {
+--
+1.7.11.4
+
diff --git a/libxml2-Change-the-XPath-code-to-percolate-allocation-errors.patch b/libxml2-Change-the-XPath-code-to-percolate-allocation-errors.patch
new file mode 100644
index 0000000..8da0cd0
--- /dev/null
+++ b/libxml2-Change-the-XPath-code-to-percolate-allocation-errors.patch
@@ -0,0 +1,484 @@
+From 5543440af0c7c2da8f292ea624cf79d7fb0a6fbf Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Wed, 5 Sep 2012 15:35:19 +0800
+Subject: [PATCH] Change the XPath code to percolate allocation errors
+To: libvir-list at redhat.com
+
+looping 1000 time on an error stating that a nodeset has
+grown out of control is useless, make sure we percolate
+error up to the various loops and break when errors occurs
+
+Conflicts:
+ xpath.c: solve a couple of context differences
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ include/libxml/xpathInternals.h | 6 +-
+ xpath.c | 156 ++++++++++++++++++++++++++--------------
+ 2 files changed, 107 insertions(+), 55 deletions(-)
+
+diff --git a/include/libxml/xpathInternals.h b/include/libxml/xpathInternals.h
+index dcd5243..02e8f46 100644
+--- a/include/libxml/xpathInternals.h
++++ b/include/libxml/xpathInternals.h
+@@ -498,13 +498,13 @@ XMLPUBFUN xmlXPathObjectPtr XMLCALL
+ xmlXPathNewNodeSet (xmlNodePtr val);
+ XMLPUBFUN xmlXPathObjectPtr XMLCALL
+ xmlXPathNewValueTree (xmlNodePtr val);
+-XMLPUBFUN void XMLCALL
++XMLPUBFUN int XMLCALL
+ xmlXPathNodeSetAdd (xmlNodeSetPtr cur,
+ xmlNodePtr val);
+-XMLPUBFUN void XMLCALL
++XMLPUBFUN int XMLCALL
+ xmlXPathNodeSetAddUnique (xmlNodeSetPtr cur,
+ xmlNodePtr val);
+-XMLPUBFUN void XMLCALL
++XMLPUBFUN int XMLCALL
+ xmlXPathNodeSetAddNs (xmlNodeSetPtr cur,
+ xmlNodePtr node,
+ xmlNsPtr ns);
+diff --git a/xpath.c b/xpath.c
+index a983f41..3936e97 100644
+--- a/xpath.c
++++ b/xpath.c
+@@ -2088,6 +2088,11 @@ xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val)
+ ret->type = XPATH_NODESET;
+ ret->boolval = 0;
+ ret->nodesetval = xmlXPathNodeSetCreate(val);
++ if (ret->nodesetval == NULL) {
++ ctxt->lastError.domain = XML_FROM_XPATH;
++ ctxt->lastError.code = XML_ERR_NO_MEMORY;
++ return(NULL);
++ }
+ #ifdef XP_DEBUG_OBJ_USAGE
+ xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
+ #endif
+@@ -3568,8 +3573,10 @@ xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
+ * @ns: a the namespace node
+ *
+ * add a new namespace node to an existing NodeSet
++ *
++ * Returns 0 in case of success and -1 in case of error
+ */
+-void
++int
+ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
+ int i;
+
+@@ -3577,7 +3584,7 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
+ if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
+ (ns->type != XML_NAMESPACE_DECL) ||
+ (node->type != XML_ELEMENT_NODE))
+- return;
++ return(-1);
+
+ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
+ /*
+@@ -3588,7 +3595,7 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
+ (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
+ (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
+ (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
+- return;
++ return(0);
+ }
+
+ /*
+@@ -3599,7 +3606,7 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
+ sizeof(xmlNodePtr));
+ if (cur->nodeTab == NULL) {
+ xmlXPathErrMemory(NULL, "growing nodeset\n");
+- return;
++ return(-1);
+ }
+ memset(cur->nodeTab, 0 ,
+ XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+@@ -3609,18 +3616,19 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
+
+ if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
+ xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
+- return;
++ return(-1);
+ }
+ temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
+ sizeof(xmlNodePtr));
+ if (temp == NULL) {
+ xmlXPathErrMemory(NULL, "growing nodeset\n");
+- return;
++ return(-1);
+ }
+ cur->nodeMax *= 2;
+ cur->nodeTab = temp;
+ }
+ cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
++ return(0);
+ }
+
+ /**
+@@ -3629,19 +3637,21 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
+ * @val: a new xmlNodePtr
+ *
+ * add a new xmlNodePtr to an existing NodeSet
++ *
++ * Returns 0 in case of success, and -1 in case of error
+ */
+-void
++int
+ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
+ int i;
+
+- if ((cur == NULL) || (val == NULL)) return;
++ if ((cur == NULL) || (val == NULL)) return(-1);
+
+ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
+ /*
+ * prevent duplcates
+ */
+ for (i = 0;i < cur->nodeNr;i++)
+- if (cur->nodeTab[i] == val) return;
++ if (cur->nodeTab[i] == val) return(0);
+
+ /*
+ * grow the nodeTab if needed
+@@ -3651,7 +3661,7 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
+ sizeof(xmlNodePtr));
+ if (cur->nodeTab == NULL) {
+ xmlXPathErrMemory(NULL, "growing nodeset\n");
+- return;
++ return(-1);
+ }
+ memset(cur->nodeTab, 0 ,
+ XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+@@ -3661,13 +3671,13 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
+
+ if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
+ xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
+- return;
++ return(-1);
+ }
+ temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
+ sizeof(xmlNodePtr));
+ if (temp == NULL) {
+ xmlXPathErrMemory(NULL, "growing nodeset\n");
+- return;
++ return(-1);
+ }
+ cur->nodeMax *= 2;
+ cur->nodeTab = temp;
+@@ -3679,6 +3689,7 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
+ xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
+ } else
+ cur->nodeTab[cur->nodeNr++] = val;
++ return(0);
+ }
+
+ /**
+@@ -3688,10 +3699,12 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
+ *
+ * add a new xmlNodePtr to an existing NodeSet, optimized version
+ * when we are sure the node is not already in the set.
++ *
++ * Returns 0 in case of success and -1 in case of failure
+ */
+-void
++int
+ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
+- if ((cur == NULL) || (val == NULL)) return;
++ if ((cur == NULL) || (val == NULL)) return(-1);
+
+ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
+ /*
+@@ -3702,7 +3715,7 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
+ sizeof(xmlNodePtr));
+ if (cur->nodeTab == NULL) {
+ xmlXPathErrMemory(NULL, "growing nodeset\n");
+- return;
++ return(-1);
+ }
+ memset(cur->nodeTab, 0 ,
+ XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+@@ -3712,13 +3725,13 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
+
+ if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
+ xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
+- return;
++ return(-1);
+ }
+ temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
+ sizeof(xmlNodePtr));
+ if (temp == NULL) {
+ xmlXPathErrMemory(NULL, "growing nodeset\n");
+- return;
++ return(-1);
+ }
+ cur->nodeTab = temp;
+ cur->nodeMax *= 2;
+@@ -3730,6 +3743,7 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
+ xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
+ } else
+ cur->nodeTab[cur->nodeNr++] = val;
++ return(0);
+ }
+
+ /**
+@@ -4326,9 +4340,12 @@ xmlXPathNewNodeSetList(xmlNodeSetPtr val)
+ ret = xmlXPathNewNodeSet(NULL);
+ else {
+ ret = xmlXPathNewNodeSet(val->nodeTab[0]);
+- if (ret)
+- for (i = 1; i < val->nodeNr; ++i)
+- xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]);
++ if (ret) {
++ for (i = 1; i < val->nodeNr; ++i) {
++ if (xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i])
++ < 0) break;
++ }
++ }
+ }
+
+ return (ret);
+@@ -4404,8 +4421,10 @@ xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
+
+ for (i = 0; i < l1; i++) {
+ cur = xmlXPathNodeSetItem(nodes1, i);
+- if (!xmlXPathNodeSetContains(nodes2, cur))
+- xmlXPathNodeSetAddUnique(ret, cur);
++ if (!xmlXPathNodeSetContains(nodes2, cur)) {
++ if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
++ break;
++ }
+ }
+ return(ret);
+ }
+@@ -4438,8 +4457,10 @@ xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
+
+ for (i = 0; i < l1; i++) {
+ cur = xmlXPathNodeSetItem(nodes1, i);
+- if (xmlXPathNodeSetContains(nodes2, cur))
+- xmlXPathNodeSetAddUnique(ret, cur);
++ if (xmlXPathNodeSetContains(nodes2, cur)) {
++ if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
++ break;
++ }
+ }
+ return(ret);
+ }
+@@ -4475,7 +4496,8 @@ xmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
+ strval = xmlXPathCastNodeToString(cur);
+ if (xmlHashLookup(hash, strval) == NULL) {
+ xmlHashAddEntry(hash, strval, strval);
+- xmlXPathNodeSetAddUnique(ret, cur);
++ if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
++ break;
+ } else {
+ xmlFree(strval);
+ }
+@@ -4567,7 +4589,8 @@ xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
+ cur = xmlXPathNodeSetItem(nodes, i);
+ if (cur == node)
+ break;
+- xmlXPathNodeSetAddUnique(ret, cur);
++ if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
++ break;
+ }
+ return(ret);
+ }
+@@ -4671,7 +4694,8 @@ xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
+ cur = xmlXPathNodeSetItem(nodes, i);
+ if (cur == node)
+ break;
+- xmlXPathNodeSetAddUnique(ret, cur);
++ if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
++ break;
+ }
+ xmlXPathNodeSetSort(ret); /* bug 413451 */
+ return(ret);
+@@ -11659,9 +11683,13 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
+ */
+ if (contextObj == NULL)
+ contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);
+- else
+- xmlXPathNodeSetAddUnique(contextObj->nodesetval,
+- contextNode);
++ else {
++ if (xmlXPathNodeSetAddUnique(contextObj->nodesetval,
++ contextNode) < 0) {
++ ctxt->error = XPATH_MEMORY_ERROR;
++ goto evaluation_exit;
++ }
++ }
+
+ valuePush(ctxt, contextObj);
+
+@@ -11807,9 +11835,13 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
+ */
+ if (contextObj == NULL)
+ contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);
+- else
+- xmlXPathNodeSetAddUnique(contextObj->nodesetval,
+- contextNode);
++ else {
++ if (xmlXPathNodeSetAddUnique(contextObj->nodesetval,
++ contextNode) < 0) {
++ ctxt->error = XPATH_MEMORY_ERROR;
++ goto evaluation_exit;
++ }
++ }
+
+ frame = xmlXPathSetFrame(ctxt);
+ valuePush(ctxt, contextObj);
+@@ -11981,22 +12013,25 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
+ #define XP_TEST_HIT \
+ if (hasAxisRange != 0) { \
+ if (++pos == maxPos) { \
+- addNode(seq, cur); \
+- goto axis_range_end; } \
++ if (addNode(seq, cur) < 0) \
++ ctxt->error = XPATH_MEMORY_ERROR; \
++ goto axis_range_end; } \
+ } else { \
+- addNode(seq, cur); \
++ if (addNode(seq, cur) < 0) \
++ ctxt->error = XPATH_MEMORY_ERROR; \
+ if (breakOnFirstHit) goto first_hit; }
+
+ #define XP_TEST_HIT_NS \
+ if (hasAxisRange != 0) { \
+ if (++pos == maxPos) { \
+ hasNsNodes = 1; \
+- xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur); \
++ if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
++ ctxt->error = XPATH_MEMORY_ERROR; \
+ goto axis_range_end; } \
+ } else { \
+ hasNsNodes = 1; \
+- xmlXPathNodeSetAddNs(seq, \
+- xpctxt->node, (xmlNsPtr) cur); \
++ if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
++ ctxt->error = XPATH_MEMORY_ERROR; \
+ if (breakOnFirstHit) goto first_hit; }
+
+ xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
+@@ -12035,7 +12070,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
+ xmlXPathTraversalFunction next = NULL;
+ /* compound axis traversal */
+ xmlXPathTraversalFunctionExt outerNext = NULL;
+- void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
++ int (*addNode) (xmlNodeSetPtr, xmlNodePtr);
+ xmlXPathNodeSetMergeFunction mergeAndClear;
+ xmlNodePtr oldContextNode;
+ xmlXPathContextPtr xpctxt = ctxt->context;
+@@ -12225,7 +12260,8 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
+ contextIdx = 0;
+
+
+- while ((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) {
++ while ((contextIdx < contextSeq->nodeNr) || (contextNode != NULL) &&
++ (ctxt->error == XPATH_EXPRESSION_OK)) {
+ if (outerNext != NULL) {
+ /*
+ * This is a compound traversal.
+@@ -12443,7 +12479,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
+ }
+ break;
+ } /* switch(test) */
+- } while (cur != NULL);
++ } while ((cur != NULL) && (ctxt->error == XPATH_EXPRESSION_OK));
+
+ goto apply_predicates;
+
+@@ -12484,6 +12520,9 @@ first_hit: /* ---------------------------------------------------------- */
+ #endif
+
+ apply_predicates: /* --------------------------------------------------- */
++ if (ctxt->error != XPATH_EXPRESSION_OK)
++ goto error;
++
+ /*
+ * Apply predicates.
+ */
+@@ -12992,8 +13031,10 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
+ tmp = xmlXPathCacheNewNodeSet(ctxt->context,
+ ctxt->context->node);
+ } else {
+- xmlXPathNodeSetAddUnique(tmp->nodesetval,
+- ctxt->context->node);
++ if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
++ ctxt->context->node) < 0) {
++ ctxt->error = XPATH_MEMORY_ERROR;
++ }
+ }
+ valuePush(ctxt, tmp);
+ if (op->ch2 != -1)
+@@ -13106,8 +13147,10 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
+ tmp = xmlXPathCacheNewNodeSet(ctxt->context,
+ ctxt->context->node);
+ } else {
+- xmlXPathNodeSetAddUnique(tmp->nodesetval,
+- ctxt->context->node);
++ if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
++ ctxt->context->node) < 0) {
++ ctxt->error = XPATH_MEMORY_ERROR;
++ }
+ }
+ valuePush(ctxt, tmp);
+ ctxt->context->contextSize = oldset->nodeNr;
+@@ -13125,7 +13168,8 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
+ */
+ res = valuePop(ctxt);
+ if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
+- xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);
++ if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]) < 0)
++ ctxt->error = XPATH_MEMORY_ERROR;
+ }
+ /*
+ * Cleanup
+@@ -13804,8 +13848,10 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
+ tmp = xmlXPathCacheNewNodeSet(ctxt->context,
+ ctxt->context->node);
+ } else {
+- xmlXPathNodeSetAddUnique(tmp->nodesetval,
+- ctxt->context->node);
++ if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
++ ctxt->context->node) < 0) {
++ ctxt->error = XPATH_MEMORY_ERROR;
++ }
+ }
+ valuePush(ctxt, tmp);
+ ctxt->context->contextSize = oldset->nodeNr;
+@@ -13835,7 +13881,9 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
+ */
+ res = valuePop(ctxt);
+ if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
+- xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);
++ if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i])
++ < 0)
++ ctxt->error = XPATH_MEMORY_ERROR;
+ }
+
+ /*
+@@ -14198,7 +14246,7 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp,
+ if (toBool)
+ return(1);
+ xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
+- (xmlNodePtr) ctxt->doc);
++ (xmlNodePtr) ctxt->doc);
+ } else {
+ /* Select "self::node()" */
+ if (toBool)
+@@ -14291,7 +14339,11 @@ next_node:
+ } else if (ret == 1) {
+ if (toBool)
+ goto return_1;
+- xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur);
++ if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur)
++ < 0) {
++ ctxt->lastError.domain = XML_FROM_XPATH;
++ ctxt->lastError.code = XML_ERR_NO_MEMORY;
++ }
+ }
+ if ((cur->children == NULL) || (depth >= max_depth)) {
+ ret = xmlStreamPop(patstream);
+--
+1.7.11.4
+
diff --git a/libxml2-Cleanups-and-new-limit-APIs-for-dictionaries.patch b/libxml2-Cleanups-and-new-limit-APIs-for-dictionaries.patch
new file mode 100644
index 0000000..3054c5a
--- /dev/null
+++ b/libxml2-Cleanups-and-new-limit-APIs-for-dictionaries.patch
@@ -0,0 +1,519 @@
+From f21e6d04502c872974df198facbf5d7787dfefb5 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Wed, 25 Jul 2012 16:32:18 +0800
+Subject: [PATCH] Cleanups and new limit APIs for dictionaries
+To: libvir-list at redhat.com
+
+* include/libxml/dict.h dict.c: adding 2 new functions xmlDictGetUsage
+ and xmlDictSetLimit allowing to review the amount of memory allocated
+ for dictionary strings. Aslo cleanup of various signed int used as
+ size values in the code.
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ dict.c | 193 ++++++++++++++++++++++++++++++++++----------------
+ include/libxml/dict.h | 6 ++
+ 2 files changed, 139 insertions(+), 60 deletions(-)
+
+diff --git a/dict.c b/dict.c
+index bd64afb..3ad89b5 100644
+--- a/dict.c
++++ b/dict.c
+@@ -19,6 +19,7 @@
+ #define IN_LIBXML
+ #include "libxml.h"
+
++#include <limits.h>
+ #ifdef HAVE_STDLIB_H
+ #include <stdlib.h>
+ #endif
+@@ -96,7 +97,7 @@ typedef xmlDictEntry *xmlDictEntryPtr;
+ struct _xmlDictEntry {
+ struct _xmlDictEntry *next;
+ const xmlChar *name;
+- int len;
++ unsigned int len;
+ int valid;
+ unsigned long okey;
+ };
+@@ -107,8 +108,8 @@ struct _xmlDictStrings {
+ xmlDictStringsPtr next;
+ xmlChar *free;
+ xmlChar *end;
+- int size;
+- int nbStrings;
++ size_t size;
++ size_t nbStrings;
+ xmlChar array[1];
+ };
+ /*
+@@ -118,13 +119,15 @@ struct _xmlDict {
+ int ref_counter;
+
+ struct _xmlDictEntry *dict;
+- int size;
+- int nbElems;
++ size_t size;
++ unsigned int nbElems;
+ xmlDictStringsPtr strings;
+
+ struct _xmlDict *subdict;
+ /* used for randomization */
+ int seed;
++ /* used to impose a limit on size */
++ size_t limit;
+ };
+
+ /*
+@@ -178,17 +181,18 @@ xmlDictCleanup(void) {
+ * xmlDictAddString:
+ * @dict: the dictionnary
+ * @name: the name of the userdata
+- * @len: the length of the name, if -1 it is recomputed
++ * @len: the length of the name
+ *
+ * Add the string to the array[s]
+ *
+ * Returns the pointer of the local string, or NULL in case of error.
+ */
+ static const xmlChar *
+-xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) {
++xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) {
+ xmlDictStringsPtr pool;
+ const xmlChar *ret;
+- int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
++ size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
++ size_t limit = 0;
+
+ #ifdef DICT_DEBUG_PATTERNS
+ fprintf(stderr, "-");
+@@ -198,15 +202,20 @@ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) {
+ if (pool->end - pool->free > namelen)
+ goto found_pool;
+ if (pool->size > size) size = pool->size;
++ limit += pool->size;
+ pool = pool->next;
+ }
+ /*
+ * Not found, need to allocate
+ */
+ if (pool == NULL) {
++ if ((dict->limit > 0) && (limit > dict->limit)) {
++ return(NULL);
++ }
++
+ if (size == 0) size = 1000;
+ else size *= 4; /* exponential growth */
+- if (size < 4 * namelen)
++ if (size < 4 * namelen)
+ size = 4 * namelen; /* just in case ! */
+ pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
+ if (pool == NULL)
+@@ -236,19 +245,20 @@ found_pool:
+ * @prefix: the prefix of the userdata
+ * @plen: the prefix length
+ * @name: the name of the userdata
+- * @len: the length of the name, if -1 it is recomputed
++ * @len: the length of the name
+ *
+ * Add the QName to the array[s]
+ *
+ * Returns the pointer of the local string, or NULL in case of error.
+ */
+ static const xmlChar *
+-xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, int plen,
+- const xmlChar *name, int namelen)
++xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, unsigned int plen,
++ const xmlChar *name, unsigned int namelen)
+ {
+ xmlDictStringsPtr pool;
+ const xmlChar *ret;
+- int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
++ size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
++ size_t limit = 0;
+
+ if (prefix == NULL) return(xmlDictAddString(dict, name, namelen));
+
+@@ -260,12 +270,17 @@ xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, int plen,
+ if (pool->end - pool->free > namelen + plen + 1)
+ goto found_pool;
+ if (pool->size > size) size = pool->size;
++ limit += pool->size;
+ pool = pool->next;
+ }
+ /*
+ * Not found, need to allocate
+ */
+ if (pool == NULL) {
++ if ((dict->limit > 0) && (limit > dict->limit)) {
++ return(NULL);
++ }
++
+ if (size == 0) size = 1000;
+ else size *= 4; /* exponential growth */
+ if (size < 4 * (namelen + plen + 1))
+@@ -482,6 +497,7 @@ xmlDictCreate(void) {
+ dict = xmlMalloc(sizeof(xmlDict));
+ if (dict) {
+ dict->ref_counter = 1;
++ dict->limit = 0;
+
+ dict->size = MIN_DICT_SIZE;
+ dict->nbElems = 0;
+@@ -559,9 +575,9 @@ xmlDictReference(xmlDictPtr dict) {
+ * Returns 0 in case of success, -1 in case of failure
+ */
+ static int
+-xmlDictGrow(xmlDictPtr dict, int size) {
++xmlDictGrow(xmlDictPtr dict, size_t size) {
+ unsigned long key, okey;
+- int oldsize, i;
++ size_t oldsize, i;
+ xmlDictEntryPtr iter, next;
+ struct _xmlDictEntry *olddict;
+ #ifdef DEBUG_GROW
+@@ -678,7 +694,7 @@ xmlDictGrow(xmlDictPtr dict, int size) {
+
+ #ifdef DEBUG_GROW
+ xmlGenericError(xmlGenericErrorContext,
+- "xmlDictGrow : from %d to %d, %d elems\n", oldsize, size, nbElem);
++ "xmlDictGrow : from %lu to %lu, %u elems\n", oldsize, size, nbElem);
+ #endif
+
+ return(ret);
+@@ -693,7 +709,7 @@ xmlDictGrow(xmlDictPtr dict, int size) {
+ */
+ void
+ xmlDictFree(xmlDictPtr dict) {
+- int i;
++ size_t i;
+ xmlDictEntryPtr iter;
+ xmlDictEntryPtr next;
+ int inside_dict = 0;
+@@ -762,17 +778,24 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
+ xmlDictEntryPtr entry;
+ xmlDictEntryPtr insert;
+ const xmlChar *ret;
++ unsigned int l;
+
+ if ((dict == NULL) || (name == NULL))
+ return(NULL);
+
+ if (len < 0)
+- len = strlen((const char *) name);
++ l = strlen((const char *) name);
++ else
++ l = len;
++
++ if (((dict->limit > 0) && (l >= dict->limit)) ||
++ (l > INT_MAX / 2))
++ return(NULL);
+
+ /*
+ * Check for duplicate and insertion location.
+ */
+- okey = xmlDictComputeKey(dict, name, len);
++ okey = xmlDictComputeKey(dict, name, l);
+ key = okey % dict->size;
+ if (dict->dict[key].valid == 0) {
+ insert = NULL;
+@@ -780,25 +803,25 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
+ for (insert = &(dict->dict[key]); insert->next != NULL;
+ insert = insert->next) {
+ #ifdef __GNUC__
+- if ((insert->okey == okey) && (insert->len == len)) {
+- if (!memcmp(insert->name, name, len))
++ if ((insert->okey == okey) && (insert->len == l)) {
++ if (!memcmp(insert->name, name, l))
+ return(insert->name);
+ }
+ #else
+- if ((insert->okey == okey) && (insert->len == len) &&
+- (!xmlStrncmp(insert->name, name, len)))
++ if ((insert->okey == okey) && (insert->l == l) &&
++ (!xmlStrncmp(insert->name, name, l)))
+ return(insert->name);
+ #endif
+ nbi++;
+ }
+ #ifdef __GNUC__
+- if ((insert->okey == okey) && (insert->len == len)) {
+- if (!memcmp(insert->name, name, len))
++ if ((insert->okey == okey) && (insert->len == l)) {
++ if (!memcmp(insert->name, name, l))
+ return(insert->name);
+ }
+ #else
+- if ((insert->okey == okey) && (insert->len == len) &&
+- (!xmlStrncmp(insert->name, name, len)))
++ if ((insert->okey == okey) && (insert->len == l) &&
++ (!xmlStrncmp(insert->name, name, l)))
+ return(insert->name);
+ #endif
+ }
+@@ -811,7 +834,7 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
+ (dict->subdict->size != MIN_DICT_SIZE)) ||
+ ((dict->size != MIN_DICT_SIZE) &&
+ (dict->subdict->size == MIN_DICT_SIZE)))
+- skey = xmlDictComputeKey(dict->subdict, name, len);
++ skey = xmlDictComputeKey(dict->subdict, name, l);
+ else
+ skey = okey;
+
+@@ -822,32 +845,32 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
+ for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
+ tmp = tmp->next) {
+ #ifdef __GNUC__
+- if ((tmp->okey == skey) && (tmp->len == len)) {
+- if (!memcmp(tmp->name, name, len))
++ if ((tmp->okey == skey) && (tmp->len == l)) {
++ if (!memcmp(tmp->name, name, l))
+ return(tmp->name);
+ }
+ #else
+- if ((tmp->okey == skey) && (tmp->len == len) &&
+- (!xmlStrncmp(tmp->name, name, len)))
++ if ((tmp->okey == skey) && (tmp->len == l) &&
++ (!xmlStrncmp(tmp->name, name, l)))
+ return(tmp->name);
+ #endif
+ nbi++;
+ }
+ #ifdef __GNUC__
+- if ((tmp->okey == skey) && (tmp->len == len)) {
+- if (!memcmp(tmp->name, name, len))
++ if ((tmp->okey == skey) && (tmp->len == l)) {
++ if (!memcmp(tmp->name, name, l))
+ return(tmp->name);
+ }
+ #else
+- if ((tmp->okey == skey) && (tmp->len == len) &&
+- (!xmlStrncmp(tmp->name, name, len)))
++ if ((tmp->okey == skey) && (tmp->len == l) &&
++ (!xmlStrncmp(tmp->name, name, l)))
+ return(tmp->name);
+ #endif
+ }
+ key = okey % dict->size;
+ }
+
+- ret = xmlDictAddString(dict, name, len);
++ ret = xmlDictAddString(dict, name, l);
+ if (ret == NULL)
+ return(NULL);
+ if (insert == NULL) {
+@@ -858,13 +881,13 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
+ return(NULL);
+ }
+ entry->name = ret;
+- entry->len = len;
++ entry->len = l;
+ entry->next = NULL;
+ entry->valid = 1;
+ entry->okey = okey;
+
+
+- if (insert != NULL)
++ if (insert != NULL)
+ insert->next = entry;
+
+ dict->nbElems++;
+@@ -893,17 +916,23 @@ const xmlChar *
+ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
+ unsigned long key, okey, nbi = 0;
+ xmlDictEntryPtr insert;
++ unsigned int l;
+
+ if ((dict == NULL) || (name == NULL))
+ return(NULL);
+
+ if (len < 0)
+- len = strlen((const char *) name);
++ l = strlen((const char *) name);
++ else
++ l = len;
++ if (((dict->limit > 0) && (l >= dict->limit)) ||
++ (l > INT_MAX / 2))
++ return(NULL);
+
+ /*
+ * Check for duplicate and insertion location.
+ */
+- okey = xmlDictComputeKey(dict, name, len);
++ okey = xmlDictComputeKey(dict, name, l);
+ key = okey % dict->size;
+ if (dict->dict[key].valid == 0) {
+ insert = NULL;
+@@ -911,25 +940,25 @@ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
+ for (insert = &(dict->dict[key]); insert->next != NULL;
+ insert = insert->next) {
+ #ifdef __GNUC__
+- if ((insert->okey == okey) && (insert->len == len)) {
+- if (!memcmp(insert->name, name, len))
++ if ((insert->okey == okey) && (insert->len == l)) {
++ if (!memcmp(insert->name, name, l))
+ return(insert->name);
+ }
+ #else
+- if ((insert->okey == okey) && (insert->len == len) &&
+- (!xmlStrncmp(insert->name, name, len)))
++ if ((insert->okey == okey) && (insert->len == l) &&
++ (!xmlStrncmp(insert->name, name, l)))
+ return(insert->name);
+ #endif
+ nbi++;
+ }
+ #ifdef __GNUC__
+- if ((insert->okey == okey) && (insert->len == len)) {
+- if (!memcmp(insert->name, name, len))
++ if ((insert->okey == okey) && (insert->len == l)) {
++ if (!memcmp(insert->name, name, l))
+ return(insert->name);
+ }
+ #else
+- if ((insert->okey == okey) && (insert->len == len) &&
+- (!xmlStrncmp(insert->name, name, len)))
++ if ((insert->okey == okey) && (insert->len == l) &&
++ (!xmlStrncmp(insert->name, name, l)))
+ return(insert->name);
+ #endif
+ }
+@@ -942,7 +971,7 @@ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
+ (dict->subdict->size != MIN_DICT_SIZE)) ||
+ ((dict->size != MIN_DICT_SIZE) &&
+ (dict->subdict->size == MIN_DICT_SIZE)))
+- skey = xmlDictComputeKey(dict->subdict, name, len);
++ skey = xmlDictComputeKey(dict->subdict, name, l);
+ else
+ skey = okey;
+
+@@ -953,25 +982,25 @@ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
+ for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
+ tmp = tmp->next) {
+ #ifdef __GNUC__
+- if ((tmp->okey == skey) && (tmp->len == len)) {
+- if (!memcmp(tmp->name, name, len))
++ if ((tmp->okey == skey) && (tmp->len == l)) {
++ if (!memcmp(tmp->name, name, l))
+ return(tmp->name);
+ }
+ #else
+- if ((tmp->okey == skey) && (tmp->len == len) &&
+- (!xmlStrncmp(tmp->name, name, len)))
++ if ((tmp->okey == skey) && (tmp->len == l) &&
++ (!xmlStrncmp(tmp->name, name, l)))
+ return(tmp->name);
+ #endif
+ nbi++;
+ }
+ #ifdef __GNUC__
+- if ((tmp->okey == skey) && (tmp->len == len)) {
+- if (!memcmp(tmp->name, name, len))
++ if ((tmp->okey == skey) && (tmp->len == l)) {
++ if (!memcmp(tmp->name, name, l))
+ return(tmp->name);
+ }
+ #else
+- if ((tmp->okey == skey) && (tmp->len == len) &&
+- (!xmlStrncmp(tmp->name, name, len)))
++ if ((tmp->okey == skey) && (tmp->len == l) &&
++ (!xmlStrncmp(tmp->name, name, l)))
+ return(tmp->name);
+ #endif
+ }
+@@ -997,7 +1026,7 @@ xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
+ xmlDictEntryPtr entry;
+ xmlDictEntryPtr insert;
+ const xmlChar *ret;
+- int len, plen, l;
++ unsigned int len, plen, l;
+
+ if ((dict == NULL) || (name == NULL))
+ return(NULL);
+@@ -1073,7 +1102,7 @@ xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
+ entry->valid = 1;
+ entry->okey = okey;
+
+- if (insert != NULL)
++ if (insert != NULL)
+ insert->next = entry;
+
+ dict->nbElems++;
+@@ -1131,6 +1160,50 @@ xmlDictSize(xmlDictPtr dict) {
+ return(dict->nbElems);
+ }
+
++/**
++ * xmlDictSetLimit:
++ * @dict: the dictionnary
++ * @limit: the limit in bytes
++ *
++ * Set a size limit for the dictionary
++ * Added in 2.9.0
++ *
++ * Returns the previous limit of the dictionary or 0
++ */
++size_t
++xmlDictSetLimit(xmlDictPtr dict, size_t limit) {
++ size_t ret;
++
++ if (dict == NULL)
++ return(0);
++ ret = dict->limit;
++ dict->limit = limit;
++ return(ret);
++}
++
++/**
++ * xmlDictGetUsage:
++ * @dict: the dictionnary
++ *
++ * Get how much memory is used by a dictionary for strings
++ * Added in 2.9.0
++ *
++ * Returns the amount of strings allocated
++ */
++size_t
++xmlDictGetUsage(xmlDictPtr dict) {
++ xmlDictStringsPtr pool;
++ size_t limit = 0;
++
++ if (dict == NULL)
++ return(0);
++ pool = dict->strings;
++ while (pool != NULL) {
++ limit += pool->size;
++ pool = pool->next;
++ }
++ return(limit);
++}
+
+ #define bottom_dict
+ #include "elfgcchack.h"
+diff --git a/include/libxml/dict.h b/include/libxml/dict.h
+index abb8339..4945be3 100644
+--- a/include/libxml/dict.h
++++ b/include/libxml/dict.h
+@@ -11,6 +11,7 @@
+ #ifndef __XML_DICT_H__
+ #define __XML_DICT_H__
+
++#include <limits.h>
+ #include <libxml/xmlversion.h>
+ #include <libxml/tree.h>
+
+@@ -29,6 +30,11 @@ typedef xmlDict *xmlDictPtr;
+ */
+ XMLPUBFUN xmlDictPtr XMLCALL
+ xmlDictCreate (void);
++XMLPUBFUN size_t XMLCALL
++ xmlDictSetLimit (xmlDictPtr dict,
++ size_t limit);
++XMLPUBFUN size_t XMLCALL
++ xmlDictGetUsage (xmlDictPtr dict);
+ XMLPUBFUN xmlDictPtr XMLCALL
+ xmlDictCreateSub(xmlDictPtr sub);
+ XMLPUBFUN int XMLCALL
+--
+1.7.11.4
+
diff --git a/libxml2-Do-not-fetch-external-parsed-entities.patch b/libxml2-Do-not-fetch-external-parsed-entities.patch
new file mode 100644
index 0000000..b9eb759
--- /dev/null
+++ b/libxml2-Do-not-fetch-external-parsed-entities.patch
@@ -0,0 +1,71 @@
+From 1928888cf378b7c670f3ef173c19c7bc5a04c624 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Mon, 23 Jul 2012 14:15:40 +0800
+Subject: [PATCH] Do not fetch external parsed entities
+To: libvir-list at redhat.com
+
+Unless explicietely asked for when validating or replacing entities
+with their value. Problem pointed out by Tom Lane <tgl at redhat.com>
+
+* parser.c: do not load external parsed entities unless needed
+* test/errors/extparsedent.xml result/errors/extparsedent.xml*:
+ add a regression test to avoid change of the behaviour in the future
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 11 +++++++++--
+ result/errors/extparsedent.xml | 5 +++++
+ test/errors/extparsedent.xml | 5 +++++
+ 3 files changed, 19 insertions(+), 2 deletions(-)
+ create mode 100644 result/errors/extparsedent.xml
+ create mode 100644 result/errors/extparsedent.xml.err
+ create mode 100644 result/errors/extparsedent.xml.str
+ create mode 100644 test/errors/extparsedent.xml
+
+diff --git a/parser.c b/parser.c
+index aa703aa..4303527 100644
+--- a/parser.c
++++ b/parser.c
+@@ -6917,8 +6917,15 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
+ * The first reference to the entity trigger a parsing phase
+ * where the ent->children is filled with the result from
+ * the parsing.
+- */
+- if (ent->checked == 0) {
++ * Note: external parsed entities will not be loaded, it is not
++ * required for a non-validating parser, unless the parsing option
++ * of validating, or substituting entities were given. Doing so is
++ * far more secure as the parser will only process data coming from
++ * the document entity by default.
++ */
++ if ((ent->checked == 0) &&
++ ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
++ (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
+ unsigned long oldnbent = ctxt->nbentities;
+
+ /*
+diff --git a/result/errors/extparsedent.xml b/result/errors/extparsedent.xml
+new file mode 100644
+index 0000000..07e4c54
+--- /dev/null
++++ b/result/errors/extparsedent.xml
+@@ -0,0 +1,5 @@
++<?xml version="1.0"?>
++<!DOCTYPE foo [
++<!ENTITY c PUBLIC "bar" "/etc/doesnotexist">
++]>
++<root>&c;</root>
+diff --git a/test/errors/extparsedent.xml b/test/errors/extparsedent.xml
+new file mode 100644
+index 0000000..07e4c54
+--- /dev/null
++++ b/test/errors/extparsedent.xml
+@@ -0,0 +1,5 @@
++<?xml version="1.0"?>
++<!DOCTYPE foo [
++<!ENTITY c PUBLIC "bar" "/etc/doesnotexist">
++]>
++<root>&c;</root>
+--
+1.7.11.4
+
diff --git a/libxml2-Enforce-XML_PARSER_EOF-state-handling-through-the-parser.patch b/libxml2-Enforce-XML_PARSER_EOF-state-handling-through-the-parser.patch
new file mode 100644
index 0000000..74c05ba
--- /dev/null
+++ b/libxml2-Enforce-XML_PARSER_EOF-state-handling-through-the-parser.patch
@@ -0,0 +1,481 @@
+From 310b309fbdbc85fc7498235b62d911fe90dce942 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Mon, 30 Jul 2012 16:16:04 +0800
+Subject: [PATCH] Enforce XML_PARSER_EOF state handling through the parser
+To: libvir-list at redhat.com
+
+That condition is one raised when the parser should positively stop
+processing further even to report errors. Best is to test is after
+most GROW call especially within loops
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 110 insertions(+), 21 deletions(-)
+
+diff --git a/parser.c b/parser.c
+index 2e633d5..78ae09b 100644
+--- a/parser.c
++++ b/parser.c
+@@ -2145,6 +2145,8 @@ xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
+ "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
+ }
+ ret = inputPush(ctxt, input);
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(-1);
+ GROW;
+ return(ret);
+ }
+@@ -2181,6 +2183,8 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
+ if (count++ > 20) {
+ count = 0;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(0);
+ }
+ if ((RAW >= '0') && (RAW <= '9'))
+ val = val * 16 + (CUR - '0');
+@@ -2212,6 +2216,8 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
+ if (count++ > 20) {
+ count = 0;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(0);
+ }
+ if ((RAW >= '0') && (RAW <= '9'))
+ val = val * 10 + (CUR - '0');
+@@ -2560,6 +2566,8 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
+ * the amount of data in the buffer.
+ */
+ GROW
++ if (ctxt->instate == XML_PARSER_EOF)
++ return;
+ if ((ctxt->input->end - ctxt->input->cur)>=4) {
+ start[0] = RAW;
+ start[1] = NXT(1);
+@@ -3178,6 +3186,8 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
+ * Handler for more complex cases
+ */
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+ c = CUR_CHAR(l);
+ if ((ctxt->options & XML_PARSE_OLD10) == 0) {
+ /*
+@@ -3229,6 +3239,8 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
+ if (count++ > 100) {
+ count = 0;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+ }
+ len += l;
+ NEXTL(l);
+@@ -3253,6 +3265,8 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
+ if (count++ > 100) {
+ count = 0;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+ }
+ len += l;
+ NEXTL(l);
+@@ -3361,6 +3375,8 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
+ }
+ count = 0;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+ }
+ len += l;
+ NEXTL(l);
+@@ -3451,6 +3467,8 @@ xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
+ const xmlChar *ret;
+
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+
+ in = ctxt->input->cur;
+ while (*in != 0 && *in == *cmp) {
+@@ -3590,6 +3608,8 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
+ #endif
+
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+ c = CUR_CHAR(l);
+
+ while (xmlIsNameChar(ctxt, c)) {
+@@ -3618,6 +3638,10 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
+ if (count++ > 100) {
+ count = 0;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF) {
++ xmlFree(buffer);
++ return(NULL);
++ }
+ }
+ if (len + 10 > max) {
+ xmlChar *tmp;
+@@ -3699,6 +3723,10 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
+ ctxt->instate = XML_PARSER_ENTITY_VALUE;
+ input = ctxt->input;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF) {
++ xmlFree(buf);
++ return(NULL);
++ }
+ NEXT;
+ c = CUR_CHAR(l);
+ /*
+@@ -3710,8 +3738,8 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
+ * In practice it means we stop the loop only when back at parsing
+ * the initial entity and the quote is found
+ */
+- while ((IS_CHAR(c)) && ((c != stop) || /* checked */
+- (ctxt->input != input))) {
++ while (((IS_CHAR(c)) && ((c != stop) || /* checked */
++ (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
+ if (len + 5 >= size) {
+ xmlChar *tmp;
+
+@@ -3740,6 +3768,10 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
+ }
+ }
+ buf[len] = 0;
++ if (ctxt->instate == XML_PARSER_EOF) {
++ xmlFree(buf);
++ return(NULL);
++ }
+
+ /*
+ * Raise problem w.r.t. '&' and '%' being used in non-entities
+@@ -3787,12 +3819,12 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
+ */
+ ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
+ 0, 0, 0);
+- if (orig != NULL)
++ if (orig != NULL)
+ *orig = buf;
+ else
+ xmlFree(buf);
+ }
+-
++
+ return(ret);
+ }
+
+@@ -3843,8 +3875,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ * OK loop until we reach one of the ending char or a size limit.
+ */
+ c = CUR_CHAR(l);
+- while ((NXT(0) != limit) && /* checked */
+- (IS_CHAR(c)) && (c != '<')) {
++ while (((NXT(0) != limit) && /* checked */
++ (IS_CHAR(c)) && (c != '<')) &&
++ (ctxt->instate != XML_PARSER_EOF)) {
+ /*
+ * Impose a reasonable limit on attribute size, unless XML_PARSE_HUGE
+ * special option is given
+@@ -3989,6 +4022,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ GROW;
+ c = CUR_CHAR(l);
+ }
++ if (ctxt->instate == XML_PARSER_EOF)
++ goto error;
++
+ if ((in_space) && (normalize)) {
+ while (buf[len - 1] == 0x20) len--;
+ }
+@@ -4021,6 +4057,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+
+ mem_error:
+ xmlErrMemory(ctxt, NULL);
++error:
+ if (buf != NULL)
+ xmlFree(buf);
+ if (rep != NULL)
+@@ -4133,6 +4170,10 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
+ if (count > 50) {
+ GROW;
+ count = 0;
++ if (ctxt->instate == XML_PARSER_EOF) {
++ xmlFree(buf);
++ return(NULL);
++ }
+ }
+ COPY_BUF(l,buf,len,cur);
+ NEXTL(l);
+@@ -4216,6 +4257,10 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
+ if (count > 50) {
+ GROW;
+ count = 0;
++ if (ctxt->instate == XML_PARSER_EOF) {
++ xmlFree(buf);
++ return(NULL);
++ }
+ }
+ NEXT;
+ cur = CUR;
+@@ -4422,6 +4467,8 @@ get_more:
+ }
+ SHRINK;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return;
+ in = ctxt->input->cur;
+ } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
+ nbchar = 0;
+@@ -4490,6 +4537,8 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
+ if (count > 50) {
+ GROW;
+ count = 0;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return;
+ }
+ NEXTL(l);
+ cur = CUR_CHAR(l);
+@@ -4701,6 +4750,10 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
+ if (count > 50) {
+ GROW;
+ count = 0;
++ if (ctxt->instate == XML_PARSER_EOF) {
++ xmlFree(buf);
++ return;
++ }
+ }
+ NEXTL(l);
+ cur = CUR_CHAR(l);
+@@ -4859,6 +4912,10 @@ get_more:
+ }
+ SHRINK;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF) {
++ xmlFree(buf);
++ return;
++ }
+ in = ctxt->input->cur;
+ if (*in == '-') {
+ if (in[1] == '-') {
+@@ -5095,6 +5152,10 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
+ count++;
+ if (count > 50) {
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF) {
++ xmlFree(buf);
++ return;
++ }
+ count = 0;
+ if ((len > XML_MAX_TEXT_LENGTH) &&
+ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
+@@ -5851,7 +5912,7 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
+ }
+ SKIP_BLANKS;
+ GROW;
+- while (RAW != '>') {
++ while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
+ const xmlChar *check = CUR_PTR;
+ int type;
+ int def;
+@@ -6000,7 +6061,7 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
+ ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
+ if (ret == NULL) return(NULL);
+ }
+- while (RAW == '|') {
++ while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
+ NEXT;
+ if (elem == NULL) {
+ ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
+@@ -6144,7 +6205,7 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
+ }
+ SKIP_BLANKS;
+ SHRINK;
+- while (RAW != ')') {
++ while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
+ /*
+ * Each loop we parse one separator and one element.
+ */
+@@ -6423,6 +6484,8 @@ xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
+ }
+ NEXT;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(-1);
+ SKIP_BLANKS;
+ if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
+ tree = xmlParseElementMixedContentDecl(ctxt, inputid);
+@@ -6590,8 +6653,8 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
+ "Entering INCLUDE Conditional Section\n");
+ }
+
+- while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
+- (NXT(2) != '>'))) {
++ while (((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
++ (NXT(2) != '>'))) && (ctxt->instate != XML_PARSER_EOF)) {
+ const xmlChar *check = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
+
+@@ -6659,7 +6722,8 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
+ if (ctxt->recovery == 0) ctxt->disableSAX = 1;
+ ctxt->instate = XML_PARSER_IGNORE;
+
+- while ((depth >= 0) && (RAW != 0)) {
++ while (((depth >= 0) && (RAW != 0)) &&
++ (ctxt->instate != XML_PARSER_EOF)) {
+ if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
+ depth++;
+ SKIP(3);
+@@ -6930,7 +6994,7 @@ xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
+ break;
+ }
+ }
+-
++
+ if (RAW != 0) {
+ xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+ }
+@@ -7383,6 +7447,8 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
+ xmlEntityPtr ent = NULL;
+
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+
+ if (RAW != '&')
+ return(NULL);
+@@ -7913,6 +7979,10 @@ xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
+ if (count++ > 100) {
+ count = 0;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF) {
++ xmlBufferFree(buf);
++ return(-1);
++ }
+ }
+ NEXTL(l);
+ c = CUR_CHAR(l);
+@@ -8146,7 +8216,7 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
+ * PEReferences.
+ * Subsequence (markupdecl | PEReference | S)*
+ */
+- while (RAW != ']') {
++ while ((RAW != ']') && (ctxt->instate != XML_PARSER_EOF)) {
+ const xmlChar *check = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
+
+@@ -8332,9 +8402,9 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
+ SKIP_BLANKS;
+ GROW;
+
+- while ((RAW != '>') &&
++ while (((RAW != '>') &&
+ ((RAW != '/') || (NXT(1) != '>')) &&
+- (IS_BYTE_CHAR(RAW))) {
++ (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
+ const xmlChar *q = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
+
+@@ -8758,6 +8828,8 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
+ if (in >= end) {
+ const xmlChar *oldbase = ctxt->input->base;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+ if (oldbase != ctxt->input->base) {
+ long delta = ctxt->input->base - oldbase;
+ start = start + delta;
+@@ -8778,6 +8850,8 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
+ if (in >= end) {
+ const xmlChar *oldbase = ctxt->input->base;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+ if (oldbase != ctxt->input->base) {
+ long delta = ctxt->input->base - oldbase;
+ start = start + delta;
+@@ -8804,6 +8878,8 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
+ if (in >= end) {
+ const xmlChar *oldbase = ctxt->input->base;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+ if (oldbase != ctxt->input->base) {
+ long delta = ctxt->input->base - oldbase;
+ start = start + delta;
+@@ -8833,6 +8909,8 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
+ if (in >= end) {
+ const xmlChar *oldbase = ctxt->input->base;
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(NULL);
+ if (oldbase != ctxt->input->base) {
+ long delta = ctxt->input->base - oldbase;
+ start = start + delta;
+@@ -9076,9 +9154,9 @@ reparse:
+ GROW;
+ if (ctxt->input->base != base) goto base_changed;
+
+- while ((RAW != '>') &&
++ while (((RAW != '>') &&
+ ((RAW != '/') || (NXT(1) != '>')) &&
+- (IS_BYTE_CHAR(RAW))) {
++ (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
+ const xmlChar *q = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
+ int len = -1, alloc = 0;
+@@ -9249,6 +9327,8 @@ skip_ns:
+ failed:
+
+ GROW
++ if (ctxt->instate == XML_PARSER_EOF)
++ break;
+ if (ctxt->input->base != base) goto base_changed;
+ if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
+ break;
+@@ -9486,6 +9566,8 @@ xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
+ * We should definitely be at the ending "S? '>'" part
+ */
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF)
++ return;
+ SKIP_BLANKS;
+ if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
+ xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
+@@ -9601,6 +9683,10 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
+ count++;
+ if (count > 50) {
+ GROW;
++ if (ctxt->instate == XML_PARSER_EOF) {
++ xmlFree(buf);
++ return;
++ }
+ count = 0;
+ }
+ NEXTL(l);
+@@ -10364,9 +10450,10 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
+
+ void
+ xmlParseMisc(xmlParserCtxtPtr ctxt) {
+- while (((RAW == '<') && (NXT(1) == '?')) ||
+- (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
+- IS_BLANK_CH(CUR)) {
++ while ((ctxt->instate != XML_PARSER_EOF) &&
++ (((RAW == '<') && (NXT(1) == '?')) ||
++ (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
++ IS_BLANK_CH(CUR))) {
+ if ((RAW == '<') && (NXT(1) == '?')) {
+ xmlParsePI(ctxt);
+ } else if (IS_BLANK_CH(CUR)) {
+@@ -11836,6 +11923,8 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
+ return(XML_ERR_INTERNAL_ERROR);
+ if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+ return(ctxt->errNo);
++ if (ctxt->instate == XML_PARSER_EOF)
++ return(-1);
+ if (ctxt->instate == XML_PARSER_START)
+ xmlDetectSAX2(ctxt);
+ if ((size > 0) && (chunk != NULL) && (!terminate) &&
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-a-failure-to-report-xmlreader-parsing-failures.patch b/libxml2-Fix-a-failure-to-report-xmlreader-parsing-failures.patch
new file mode 100644
index 0000000..5030cc0
--- /dev/null
+++ b/libxml2-Fix-a-failure-to-report-xmlreader-parsing-failures.patch
@@ -0,0 +1,37 @@
+From 4dae20fb28932b14b47d7cb0e8cd278270887a52 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Wed, 18 Jul 2012 17:39:56 +0800
+Subject: [PATCH] Fix a failure to report xmlreader parsing failures
+To: libvir-list at redhat.com
+
+Related to https://bugzilla.gnome.org/show_bug.cgi?id=654567
+the problem is that the provided patch failed to raise an error
+on xmlTextReaderRead() return when an actual parsing error occured
+
+Conflicts:
+ xmlreader.c: context change
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ xmlreader.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/xmlreader.c b/xmlreader.c
+index 97c71ab..12b777f 100644
+--- a/xmlreader.c
++++ b/xmlreader.c
+@@ -900,6 +900,11 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
+ }
+ }
+ reader->state = oldstate;
++ if (reader->ctxt->wellFormed == 0) {
++ reader->mode = XML_TEXTREADER_MODE_EOF;
++ return(-1);
++ }
++
+ return(0);
+ }
+
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-a-potential-freeing-error-in-XPath.patch b/libxml2-Fix-a-potential-freeing-error-in-XPath.patch
new file mode 100644
index 0000000..707ad1a
--- /dev/null
+++ b/libxml2-Fix-a-potential-freeing-error-in-XPath.patch
@@ -0,0 +1,38 @@
+From 0817eafbc02dfb113f0ca9d3b99dd9ef72a37ed8 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Wed, 17 Nov 2010 14:12:14 +0100
+Subject: [PATCH] Fix a potential freeing error in XPath
+To: libvir-list at redhat.com
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ xpath.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/xpath.c b/xpath.c
+index 4d6826d..5474849 100644
+--- a/xpath.c
++++ b/xpath.c
+@@ -11763,11 +11763,15 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
+
+ if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {
+ xmlXPathObjectPtr tmp;
+- /* pop the result */
++ /* pop the result if any */
+ tmp = valuePop(ctxt);
+- xmlXPathReleaseObject(xpctxt, tmp);
+- /* then pop off contextObj, which will be freed later */
+- valuePop(ctxt);
++ if (tmp != contextObj)
++ /*
++ * Free up the result
++ * then pop off contextObj, which will be freed later
++ */
++ xmlXPathReleaseObject(xpctxt, tmp);
++ valuePop(ctxt);
+ goto evaluation_error;
+ }
+
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-a-segfault-on-XSD-validation-on-pattern-error.patch b/libxml2-Fix-a-segfault-on-XSD-validation-on-pattern-error.patch
new file mode 100644
index 0000000..4f0263a
--- /dev/null
+++ b/libxml2-Fix-a-segfault-on-XSD-validation-on-pattern-error.patch
@@ -0,0 +1,56 @@
+From 525b6f62bc3727a5297e202291b3cc171a6b68b2 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Fri, 17 Aug 2012 20:34:05 +0800
+Subject: [PATCH] Fix a segfault on XSD validation on pattern error
+To: libvir-list at redhat.com
+
+As reported by Sven <sven at e7o.de>:
+The following pattern will cause a segmentation fault in my
+Apache (using PHP5 to validate a XML against a XSD):
+
+<xs:pattern value="(.*)|"/>
+
+Fix a cascade of error handling failures which led to the
+crash in that scenario.
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ xmlregexp.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/xmlregexp.c b/xmlregexp.c
+index aaff33e..c574ad3 100644
+--- a/xmlregexp.c
++++ b/xmlregexp.c
+@@ -3199,7 +3199,7 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
+ memset(exec->counts, 0, comp->nbCounters * sizeof(int));
+ } else
+ exec->counts = NULL;
+- while ((exec->status == 0) &&
++ while ((exec->status == 0) && (exec->state != NULL) &&
+ ((exec->inputString[exec->index] != 0) ||
+ ((exec->state != NULL) &&
+ (exec->state->type != XML_REGEXP_FINAL_STATE)))) {
+@@ -3453,6 +3453,8 @@ error:
+ }
+ xmlFree(exec->rollbacks);
+ }
++ if (exec->state == NULL)
++ return(-1);
+ if (exec->counts != NULL)
+ xmlFree(exec->counts);
+ if (exec->status == 0)
+@@ -5370,6 +5372,10 @@ xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) {
+ end = ctxt->state;
+ while ((CUR == '|') && (ctxt->error == 0)) {
+ NEXT;
++ if (CUR == 0) {
++ ERROR("expecting a branch after |")
++ return;
++ }
+ ctxt->state = start;
+ ctxt->end = NULL;
+ xmlFAParseBranch(ctxt, end);
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-an-allocation-error-when-copying-entities.patch b/libxml2-Fix-an-allocation-error-when-copying-entities.patch
new file mode 100644
index 0000000..886e697
--- /dev/null
+++ b/libxml2-Fix-an-allocation-error-when-copying-entities.patch
@@ -0,0 +1,27 @@
+From bc55cdaa736850127c08b557df01fbee77c82824 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Fri, 16 Dec 2011 18:53:35 +0800
+Subject: [PATCH] Fix an allocation error when copying entities
+To: libvir-list at redhat.com
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/parser.c b/parser.c
+index ef00f42..7743d20 100644
+--- a/parser.c
++++ b/parser.c
+@@ -2709,7 +2709,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
+
+ buffer[nbchars++] = '&';
+ if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
+- growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
++ growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
+ }
+ for (;i > 0;i--)
+ buffer[nbchars++] = *cur++;
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-an-error-in-previous-commit.patch b/libxml2-Fix-an-error-in-previous-commit.patch
new file mode 100644
index 0000000..323a2b5
--- /dev/null
+++ b/libxml2-Fix-an-error-in-previous-commit.patch
@@ -0,0 +1,27 @@
+From 9ab7a91a2e1c37bc8d98cd165d62c479b032143e Mon Sep 17 00:00:00 2001
+From: Aron Xu <happyaron.xu at gmail.com>
+Date: Fri, 20 Jul 2012 15:41:34 +0800
+Subject: [PATCH] Fix an error in previous commit
+To: libvir-list at redhat.com
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ entities.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/entities.c b/entities.c
+index 859ec3b..7d06820 100644
+--- a/entities.c
++++ b/entities.c
+@@ -529,7 +529,7 @@ xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
+ */
+ #define growBufferReentrant() { \
+ xmlChar *tmp; \
+- size_t new_size = buffer_size *= 2; \
++ 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; \
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-an-off-by-one-error-in-encoding.patch b/libxml2-Fix-an-off-by-one-error-in-encoding.patch
new file mode 100644
index 0000000..c4dcc6e
--- /dev/null
+++ b/libxml2-Fix-an-off-by-one-error-in-encoding.patch
@@ -0,0 +1,39 @@
+From 463fd3346a04d6d0c6ec4820fc701d9a1c160458 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Fri, 19 Aug 2011 11:05:04 +0800
+Subject: [PATCH] Fix an off by one error in encoding
+To: libvir-list at redhat.com
+
+this off by one error doesn't seems to reproduce on linux
+but the error is real.
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ encoding.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/encoding.c b/encoding.c
+index d1140bf..fb0c38a 100644
+--- a/encoding.c
++++ b/encoding.c
+@@ -1928,7 +1928,7 @@ xmlCharEncFirstLineInt(xmlCharEncodingHandler *handler, xmlBufferPtr out,
+ 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 @@ xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out,
+ 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;
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-an-off-by-one-pointer-access.patch b/libxml2-Fix-an-off-by-one-pointer-access.patch
new file mode 100644
index 0000000..e7e2413
--- /dev/null
+++ b/libxml2-Fix-an-off-by-one-pointer-access.patch
@@ -0,0 +1,46 @@
+From 15f9281daa9fa8389ede04085ff3941883d2c3a6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?J=C3=BCri=20Aedla?= <asd at ut.ee>
+Date: Mon, 7 May 2012 15:06:56 +0800
+Subject: [PATCH] Fix an off by one pointer access
+To: libvir-list at redhat.com
+
+getting out of the range of memory allocated for xpointer decoding
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ xpointer.c | 15 ++++-----------
+ 1 file changed, 4 insertions(+), 11 deletions(-)
+
+diff --git a/xpointer.c b/xpointer.c
+index 37afa3a..0b463dd 100644
+--- a/xpointer.c
++++ b/xpointer.c
+@@ -1007,21 +1007,14 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
+ 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;
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-an-unimplemented-part-in-RNG-value-validation.patch b/libxml2-Fix-an-unimplemented-part-in-RNG-value-validation.patch
new file mode 100644
index 0000000..d1fe048
--- /dev/null
+++ b/libxml2-Fix-an-unimplemented-part-in-RNG-value-validation.patch
@@ -0,0 +1,67 @@
+From 5974c1e350fddbced412b9442eaf5cfbb012bfc2 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Thu, 10 Nov 2011 18:08:33 +0800
+Subject: [PATCH] Fix an unimplemented part in RNG value validation
+To: libvir-list at redhat.com
+
+Forgot to implement <optional> this was raised again
+in https://bugzilla.redhat.com/show_bug.cgi?id=752393
+as this make libxml2 fail to validate against ODF RNGs
+
+Daniel
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ relaxng.c | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+diff --git a/relaxng.c b/relaxng.c
+index 6dbc499..c0ac3b7 100644
+--- a/relaxng.c
++++ b/relaxng.c
+@@ -8884,6 +8884,11 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
+ case XML_RELAXNG_ZEROORMORE:{
+ xmlChar *cur, *temp;
+
++ if ((ctxt->state->value == NULL) ||
++ (*ctxt->state->value == 0)) {
++ ret = 0;
++ break;
++ }
+ oldflags = ctxt->flags;
+ ctxt->flags |= FLAGS_IGNORABLE;
+ cur = ctxt->state->value;
+@@ -8905,6 +8910,30 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGPopErrors(ctxt, 0);
+ break;
+ }
++ case XML_RELAXNG_OPTIONAL:{
++ xmlChar *temp;
++
++ if ((ctxt->state->value == NULL) ||
++ (*ctxt->state->value == 0)) {
++ ret = 0;
++ break;
++ }
++ oldflags = ctxt->flags;
++ ctxt->flags |= FLAGS_IGNORABLE;
++ temp = ctxt->state->value;
++ ret = xmlRelaxNGValidateValue(ctxt, define->content);
++ ctxt->flags = oldflags;
++ if (ret != 0) {
++ ctxt->state->value = temp;
++ if (ctxt->errNr > 0)
++ xmlRelaxNGPopErrors(ctxt, 0);
++ ret = 0;
++ break;
++ }
++ if (ctxt->errNr > 0)
++ xmlRelaxNGPopErrors(ctxt, 0);
++ break;
++ }
+ case XML_RELAXNG_EXCEPT:{
+ xmlRelaxNGDefinePtr list;
+
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-entities-local-buffers-size-problems.patch b/libxml2-Fix-entities-local-buffers-size-problems.patch
new file mode 100644
index 0000000..0aa048b
--- /dev/null
+++ b/libxml2-Fix-entities-local-buffers-size-problems.patch
@@ -0,0 +1,103 @@
+From da2b4fffc2854d8d66f98beb09354543881c9f40 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Wed, 18 Jul 2012 11:38:17 +0800
+Subject: [PATCH] Fix entities local buffers size problems
+To: libvir-list at redhat.com
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ entities.c | 36 +++++++++++++++++++++++-------------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/entities.c b/entities.c
+index 6aef49f..859ec3b 100644
+--- a/entities.c
++++ b/entities.c
+@@ -528,13 +528,13 @@ xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
+ * 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 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
+ 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 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
+ 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 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
+ }
+ *out = 0;
+ return(buffer);
++
++mem_error:
++ xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");
++ xmlFree(buffer);
++ return(NULL);
+ }
+
+ /**
+@@ -709,7 +714,7 @@ xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, const xmlChar *input) {
+ 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 @@ xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, const xmlChar *input) {
+ 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 @@ xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, const xmlChar *input) {
+ }
+ *out = 0;
+ return(buffer);
++
++mem_error:
++ xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed");
++ xmlFree(buffer);
++ return(NULL);
+ }
+
+ /**
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-missing-error-status-in-XPath-evaluation.patch b/libxml2-Fix-missing-error-status-in-XPath-evaluation.patch
new file mode 100644
index 0000000..3627be1
--- /dev/null
+++ b/libxml2-Fix-missing-error-status-in-XPath-evaluation.patch
@@ -0,0 +1,69 @@
+From accdfd7edc118f8c6a92747977bb301da6ca6c2e Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Tue, 11 Oct 2011 16:34:34 +0800
+Subject: [PATCH] Fix missing error status in XPath evaluation
+To: libvir-list at redhat.com
+
+Started by Chris Evans, I added a few more place where the
+error should have been set in the evaluation context.
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ xpath.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/xpath.c b/xpath.c
+index bf425ee..713b43c 100644
+--- a/xpath.c
++++ b/xpath.c
+@@ -2485,6 +2485,7 @@ valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
+ sizeof(ctxt->valueTab[0]));
+ if (tmp == NULL) {
+ xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
++ ctxt->error = XPATH_MEMORY_ERROR;
+ return (0);
+ }
+ ctxt->valueMax *= 2;
+@@ -9340,6 +9341,7 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+ if ( (ch & 0xc0) != 0xc0 ) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlXPathTranslateFunction: Invalid UTF8 string\n");
++ /* not asserting an XPath error is probably better */
+ break;
+ }
+ /* then skip over remaining bytes for this char */
+@@ -9347,6 +9349,7 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+ if ( (*cptr++ & 0xc0) != 0x80 ) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlXPathTranslateFunction: Invalid UTF8 string\n");
++ /* not asserting an XPath error is probably better */
+ break;
+ }
+ if (ch & 0x80) /* must have had error encountered */
+@@ -13411,6 +13414,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
+ 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,
+@@ -13465,6 +13469,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
+ "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
+ (char *)op->value4, (char *)op->value5);
+ xmlXPathPopFrame(ctxt, frame);
++ ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
+ return (total);
+ }
+ func = xmlXPathFunctionLookupNS(ctxt->context,
+@@ -14043,6 +14048,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
+ }
+ xmlGenericError(xmlGenericErrorContext,
+ "XPath: unknown precompiled operation %d\n", op->op);
++ ctxt->error = XPATH_INVALID_OPERAND;
+ return (total);
+ }
+
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-parser-local-buffers-size-problems.patch b/libxml2-Fix-parser-local-buffers-size-problems.patch
new file mode 100644
index 0000000..d6288c0
--- /dev/null
+++ b/libxml2-Fix-parser-local-buffers-size-problems.patch
@@ -0,0 +1,269 @@
+From 03c10b4b4cfcc2d25b78106b65ed24a968113e2b Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Tue, 17 Jul 2012 16:19:17 +0800
+Subject: [PATCH] Fix parser local buffers size problems
+To: libvir-list at redhat.com
+
+Conflicts:
+ parser.c: context changes
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 74 +++++++++++++++++++++++++++++++++++++---------------------------
+ 1 file changed, 43 insertions(+), 31 deletions(-)
+
+diff --git a/parser.c b/parser.c
+index 7743d20..aa703aa 100644
+--- a/parser.c
++++ b/parser.c
+@@ -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 @@ xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
+ * 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 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
+
+ /*
+ * 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 @@ xmlChar *
+ 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 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
+ * 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 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
+ 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 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
+ (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 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
+ 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,7 +2710,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
+ const xmlChar *cur = ent->name;
+
+ buffer[nbchars++] = '&';
+- if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
++ if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
+ growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
+ }
+ for (;i > 0;i--)
+@@ -2736,8 +2738,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
+ 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 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
+ } 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 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ 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 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ * 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 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+
+ if (val == '&') {
+ if (ctxt->replaceEntities) {
+- if (len > buf_size - 10) {
++ if (len + 10 > buf_size) {
+ growBuffer(buf, 10);
+ }
+ buf[len++] = '&';
+@@ -3804,7 +3805,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ * 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 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ 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 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ 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 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ current++;
+ } else
+ buf[len++] = *current++;
+- if (len > buf_size - 10) {
++ if (len + 10 > buf_size) {
+ growBuffer(buf, 10);
+ }
+ }
+@@ -3862,7 +3863,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ rep = NULL;
+ }
+ } else {
+- if (len > buf_size - 10) {
++ if (len + 10 > buf_size) {
+ growBuffer(buf, 10);
+ }
+ if (ent->content != NULL)
+@@ -3890,7 +3891,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ * 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 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ 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 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ } 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 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ }
+ } 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:
+--
+1.7.11.4
+
diff --git a/libxml2-Fix-some-potential-problems-on-reallocation-failures.patch b/libxml2-Fix-some-potential-problems-on-reallocation-failures.patch
new file mode 100644
index 0000000..8d894e7
--- /dev/null
+++ b/libxml2-Fix-some-potential-problems-on-reallocation-failures.patch
@@ -0,0 +1,108 @@
+From e4f7cd441de5804a989bff3ab4993f2f62751a89 Mon Sep 17 00:00:00 2001
+From: Chris Evans <scarybeasts at gmail.com>
+Date: Wed, 23 Mar 2011 08:13:06 +0800
+Subject: [PATCH] Fix some potential problems on reallocation failures
+To: libvir-list at redhat.com
+
+The count was incremented before the allocation
+and not fixed in case of failure
+* xpath.c: corrects a few instances where the available count of some
+ structure is updated before we know the allocation actually
+ succeeds
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ xpath.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/xpath.c b/xpath.c
+index eef69f7..756220b 100644
+--- a/xpath.c
++++ b/xpath.c
+@@ -3522,13 +3522,13 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
+ } 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 +3627,14 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
+ } 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 +3738,14 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
+ } 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 +3907,14 @@ xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
+ } 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 +3991,14 @@ xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
+ } 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;
+ }
+--
+1.7.11.4
+
diff --git a/libxml2-Fixup-limits-parser.patch b/libxml2-Fixup-limits-parser.patch
new file mode 100644
index 0000000..be1c2bb
--- /dev/null
+++ b/libxml2-Fixup-limits-parser.patch
@@ -0,0 +1,26 @@
+From c1356d70aa478f6a3d4dbab86b9e8b849a13323c Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Mon, 30 Jul 2012 15:41:10 +0800
+Subject: [PATCH] Fixup limits parser
+To: libvir-list at redhat.com
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/parser.c b/parser.c
+index b54fbc4..2e633d5 100644
+--- a/parser.c
++++ b/parser.c
+@@ -1999,6 +1999,7 @@ static void xmlGROW (xmlParserCtxtPtr ctxt) {
+ ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
+ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
+ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
++ ctxt->instate = XML_PARSER_EOF;
+ }
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+ if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
+--
+1.7.11.4
+
diff --git a/libxml2-Hardening-of-XPath-evaluation.patch b/libxml2-Hardening-of-XPath-evaluation.patch
new file mode 100644
index 0000000..3f82664
--- /dev/null
+++ b/libxml2-Hardening-of-XPath-evaluation.patch
@@ -0,0 +1,233 @@
+From e9bbfe6e96d6c36f013612b1d90cf14a489d451a Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Thu, 18 Aug 2011 17:10:13 +0800
+Subject: [PATCH] Hardening of XPath evaluation
+To: libvir-list at redhat.com
+
+Add a mechanism of frame for XPath evaluation when entering a function
+or a scoped evaluation, also fix a potential problem in predicate
+evaluation.
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ include/libxml/xpath.h | 5 +++-
+ xpath.c | 69 +++++++++++++++++++++++++++++++++++++++++++++-----
+ xpointer.c | 1 +
+ 3 files changed, 68 insertions(+), 7 deletions(-)
+
+diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
+index 1a9e30e..ddd9dd8 100644
+--- a/include/libxml/xpath.h
++++ b/include/libxml/xpath.h
+@@ -68,7 +68,8 @@ typedef enum {
+ 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 @@ struct _xmlXPathParserContext {
+ 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 */
+ };
+
+ /************************************************************************
+diff --git a/xpath.c b/xpath.c
+index 756220b..bf425ee 100644
+--- a/xpath.c
++++ b/xpath.c
+@@ -252,6 +252,7 @@ static const char *xmlXPathErrorMessages[] = {
+ "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 @@ xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) {
+ ************************************************************************/
+
+ /**
++ * 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 @@ valuePop(xmlXPathParserContextPtr ctxt)
+
+ 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];
+@@ -6154,6 +6197,7 @@ xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
+ ret->valueNr = 0;
+ ret->valueMax = 10;
+ ret->value = NULL;
++ ret->valueFrame = 0;
+
+ ret->context = ctxt;
+ ret->comp = comp;
+@@ -11712,6 +11756,7 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
+ xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
+ xmlNodePtr oldContextNode, contextNode = NULL;
+ xmlXPathContextPtr xpctxt = ctxt->context;
++ int frame;
+
+ #ifdef LIBXML_XPTR_ENABLED
+ /*
+@@ -11731,6 +11776,8 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
+ */
+ exprOp = &ctxt->comp->steps[op->ch2];
+ for (i = 0; i < set->nodeNr; i++) {
++ xmlXPathObjectPtr tmp;
++
+ if (set->nodeTab[i] == NULL)
+ continue;
+
+@@ -11758,23 +11805,25 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
+ 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 if any */
+- tmp = valuePop(ctxt);
+- if (tmp != contextObj) {
++ while (tmp != contextObj) {
+ /*
+ * Free up the result
+ * then pop off contextObj, which will be freed later
+ */
+ xmlXPathReleaseObject(xpctxt, tmp);
+- valuePop(ctxt);
++ tmp = valuePop(ctxt);
+ }
+ goto evaluation_error;
+ }
++ /* push the result back onto the stack */
++ valuePush(ctxt, tmp);
+
+ if (res)
+ pos++;
+@@ -13378,7 +13427,9 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
+ xmlXPathFunction func;
+ const xmlChar *oldFunc, *oldFuncURI;
+ int i;
++ int frame;
+
++ frame = xmlXPathSetFrame(ctxt);
+ if (op->ch1 != -1)
+ total +=
+ xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
+@@ -13386,15 +13437,18 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
+ 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 {
+@@ -13410,6 +13464,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
+ (char *)op->value4, (char *)op->value5);
++ xmlXPathPopFrame(ctxt, frame);
+ return (total);
+ }
+ func = xmlXPathFunctionLookupNS(ctxt->context,
+@@ -13431,6 +13486,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
+ func(ctxt, op->value);
+ ctxt->context->function = oldFunc;
+ ctxt->context->functionURI = oldFuncURI;
++ xmlXPathPopFrame(ctxt, frame);
+ return (total);
+ }
+ case XPATH_OP_ARG:
+@@ -14334,6 +14390,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
+ ctxt->valueNr = 0;
+ ctxt->valueMax = 10;
+ ctxt->value = NULL;
++ ctxt->valueFrame = 0;
+ }
+ #ifdef XPATH_STREAMING
+ if (ctxt->comp->stream) {
+diff --git a/xpointer.c b/xpointer.c
+index 7a42d02..37afa3a 100644
+--- a/xpointer.c
++++ b/xpointer.c
+@@ -1269,6 +1269,7 @@ xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) {
+ ctxt->valueNr = 0;
+ ctxt->valueMax = 10;
+ ctxt->value = NULL;
++ ctxt->valueFrame = 0;
+ }
+ SKIP_BLANKS;
+ if (CUR == '/') {
+--
+1.7.11.4
+
diff --git a/libxml2-Implement-some-default-limits-in-the-XPath-module.patch b/libxml2-Implement-some-default-limits-in-the-XPath-module.patch
new file mode 100644
index 0000000..1cf58eb
--- /dev/null
+++ b/libxml2-Implement-some-default-limits-in-the-XPath-module.patch
@@ -0,0 +1,328 @@
+From 7f999c167a0a41a20c9cae84a0f06d89c00d8e0b Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Mon, 30 Jul 2012 10:12:18 +0800
+Subject: [PATCH] Implement some default limits in the XPath module
+To: libvir-list at redhat.com
+
+This adds some internal limitationson XPath expression complexity,
+and limits at runtime like depth of the stack and maximum size
+for nodeset.
+* xpath.c: implement the above as well as the maximum Name lenght
+
+Conflicts:
+ xpath.c: some context change
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ xpath.c | 163 +++++++++++++++++++++++++++++++++-------------------------------
+ 1 file changed, 83 insertions(+), 80 deletions(-)
+
+diff --git a/xpath.c b/xpath.c
+index 713b43c..a983f41 100644
+--- a/xpath.c
++++ b/xpath.c
+@@ -90,6 +90,34 @@
+ /* #define XP_DEBUG_OBJ_USAGE */
+
+ /*
++ * XPATH_MAX_STEPS:
++ * when compiling an XPath expression we arbitrary limit the maximum
++ * number of step operation in the compiled expression. 1000000 is
++ * an insanely large value which should never be reached under normal
++ * circumstances
++ */
++#define XPATH_MAX_STEPS 1000000
++
++/*
++ * XPATH_MAX_STACK_DEPTH:
++ * when evaluating an XPath expression we arbitrary limit the maximum
++ * number of object allowed to be pushed on the stack. 1000000 is
++ * an insanely large value which should never be reached under normal
++ * circumstances
++ */
++#define XPATH_MAX_STACK_DEPTH 1000000
++
++/*
++ * XPATH_MAX_NODESET_LENGTH:
++ * when evaluating an XPath expression nodesets are created and we
++ * arbitrary limit the maximum length of those node set. 10000000 is
++ * an insanely large value which should never be reached under normal
++ * circumstances, one would first need to construct an in memory tree
++ * with more than 10 millions nodes.
++ */
++#define XPATH_MAX_NODESET_LENGTH 10000000
++
++/*
+ * TODO:
+ * There are a few spots where some tests are done which depend upon ascii
+ * data. These should be enhanced for full UTF8 support (see particularly
+@@ -420,8 +448,7 @@ xmlPointerListAddSize(xmlPointerListPtr list,
+ if (list->items == NULL) {
+ if (initialSize <= 0)
+ initialSize = 1;
+- list->items = (void **) xmlMalloc(
+- initialSize * sizeof(void *));
++ list->items = (void **) xmlMalloc(initialSize * sizeof(void *));
+ if (list->items == NULL) {
+ xmlXPathErrMemory(NULL,
+ "xmlPointerListCreate: allocating item\n");
+@@ -430,12 +457,17 @@ xmlPointerListAddSize(xmlPointerListPtr list,
+ list->number = 0;
+ list->size = initialSize;
+ } else if (list->size <= list->number) {
++ if (list->size > 50000000) {
++ xmlXPathErrMemory(NULL,
++ "xmlPointerListAddSize: re-allocating item\n");
++ return(-1);
++ }
+ list->size *= 2;
+ list->items = (void **) xmlRealloc(list->items,
+ list->size * sizeof(void *));
+ if (list->items == NULL) {
+ xmlXPathErrMemory(NULL,
+- "xmlPointerListCreate: re-allocating item\n");
++ "xmlPointerListAddSize: re-allocating item\n");
+ list->size = 0;
+ return(-1);
+ }
+@@ -723,6 +755,10 @@ xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
+ if (comp->nbStep >= comp->maxStep) {
+ xmlXPathStepOp *real;
+
++ if (comp->maxStep >= XPATH_MAX_STEPS) {
++ xmlXPathErrMemory(NULL, "adding step\n");
++ return(-1);
++ }
+ comp->maxStep *= 2;
+ real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
+ comp->maxStep * sizeof(xmlXPathStepOp));
+@@ -2480,11 +2516,16 @@ valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
+ if (ctxt->valueNr >= ctxt->valueMax) {
+ xmlXPathObjectPtr *tmp;
+
++ if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) {
++ xmlXPathErrMemory(NULL, "XPath stack depth limit reached\n");
++ ctxt->error = XPATH_MEMORY_ERROR;
++ return (0);
++ }
+ tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
+ 2 * ctxt->valueMax *
+ sizeof(ctxt->valueTab[0]));
+ if (tmp == NULL) {
+- xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
++ xmlXPathErrMemory(NULL, "pushing value\n");
+ ctxt->error = XPATH_MEMORY_ERROR;
+ return (0);
+ }
+@@ -3566,6 +3607,10 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
+ } else if (cur->nodeNr == cur->nodeMax) {
+ xmlNodePtr *temp;
+
++ if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
++ xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
++ return;
++ }
+ temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
+ sizeof(xmlNodePtr));
+ if (temp == NULL) {
+@@ -3591,11 +3636,6 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
+
+ if ((cur == NULL) || (val == NULL)) return;
+
+-#if 0
+- if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
+- return; /* an XSLT fake node */
+-#endif
+-
+ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
+ /*
+ * prevent duplcates
+@@ -3619,13 +3659,17 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
+ } else if (cur->nodeNr == cur->nodeMax) {
+ xmlNodePtr *temp;
+
+- cur->nodeMax *= 2;
+- temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
+- sizeof(xmlNodePtr));
++ if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
++ xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
++ return;
++ }
++ 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;
+ }
+ if (val->type == XML_NAMESPACE_DECL) {
+@@ -3649,11 +3693,6 @@ void
+ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
+ if ((cur == NULL) || (val == NULL)) return;
+
+-#if 0
+- if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
+- return; /* an XSLT fake node */
+-#endif
+-
+ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
+ /*
+ * grow the nodeTab if needed
+@@ -3671,6 +3710,10 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
+ } else if (cur->nodeNr == cur->nodeMax) {
+ xmlNodePtr *temp;
+
++ if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
++ xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
++ return;
++ }
+ temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
+ sizeof(xmlNodePtr));
+ if (temp == NULL) {
+@@ -3782,6 +3825,10 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
+ } else if (val1->nodeNr == val1->nodeMax) {
+ xmlNodePtr *temp;
+
++ if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
++ xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
++ return(NULL);
++ }
+ temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
+ sizeof(xmlNodePtr));
+ if (temp == NULL) {
+@@ -3803,68 +3850,6 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
+ return(val1);
+ }
+
+-#if 0 /* xmlXPathNodeSetMergeUnique() is currently not used anymore */
+-/**
+- * xmlXPathNodeSetMergeUnique:
+- * @val1: the first NodeSet or NULL
+- * @val2: the second NodeSet
+- *
+- * Merges two nodesets, all nodes from @val2 are added to @val1
+- * if @val1 is NULL, a new set is created and copied from @val2
+- *
+- * Returns @val1 once extended or NULL in case of error.
+- */
+-static xmlNodeSetPtr
+-xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
+- int i;
+-
+- if (val2 == NULL) return(val1);
+- if (val1 == NULL) {
+- val1 = xmlXPathNodeSetCreate(NULL);
+- }
+- if (val1 == NULL)
+- return (NULL);
+-
+- /* @@ with_ns to check whether namespace nodes should be looked at @@ */
+-
+- for (i = 0;i < val2->nodeNr;i++) {
+- /*
+- * grow the nodeTab if needed
+- */
+- if (val1->nodeMax == 0) {
+- val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
+- sizeof(xmlNodePtr));
+- if (val1->nodeTab == NULL) {
+- xmlXPathErrMemory(NULL, "merging nodeset\n");
+- return(NULL);
+- }
+- memset(val1->nodeTab, 0 ,
+- XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+- val1->nodeMax = XML_NODESET_DEFAULT;
+- } else if (val1->nodeNr == val1->nodeMax) {
+- xmlNodePtr *temp;
+-
+- val1->nodeMax *= 2;
+- temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
+- sizeof(xmlNodePtr));
+- if (temp == NULL) {
+- xmlXPathErrMemory(NULL, "merging nodeset\n");
+- return(NULL);
+- }
+- val1->nodeTab = temp;
+- }
+- if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
+- xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
+-
+- val1->nodeTab[val1->nodeNr++] =
+- xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
+- } else
+- val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
+- }
+-
+- return(val1);
+-}
+-#endif /* xmlXPathNodeSetMergeUnique() is currently not used anymore */
+
+ /**
+ * xmlXPathNodeSetMergeAndClear:
+@@ -3951,6 +3936,10 @@ xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
+ } else if (set1->nodeNr >= set1->nodeMax) {
+ xmlNodePtr *temp;
+
++ if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
++ xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
++ return(NULL);
++ }
+ temp = (xmlNodePtr *) xmlRealloc(
+ set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
+ if (temp == NULL) {
+@@ -4035,6 +4024,10 @@ xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
+ } else if (set1->nodeNr >= set1->nodeMax) {
+ xmlNodePtr *temp;
+
++ if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
++ xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
++ return(NULL);
++ }
+ temp = (xmlNodePtr *) xmlRealloc(
+ set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
+ if (temp == NULL) {
+@@ -9866,7 +9859,7 @@ xmlChar *
+ xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
+ const xmlChar *in;
+ xmlChar *ret;
+- int count = 0;
++ size_t count = 0;
+
+ if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
+ /*
+@@ -9885,6 +9878,10 @@ xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
+ in++;
+ if ((*in > 0) && (*in < 0x80)) {
+ count = in - ctxt->cur;
++ if (count > XML_MAX_NAME_LENGTH) {
++ ctxt->cur = in;
++ XP_ERRORNULL(XPATH_EXPR_ERROR);
++ }
+ ret = xmlStrndup(ctxt->cur, count);
+ ctxt->cur = in;
+ return(ret);
+@@ -9928,6 +9925,9 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
+ xmlChar *buffer;
+ int max = len * 2;
+
++ if (len > XML_MAX_NAME_LENGTH) {
++ XP_ERRORNULL(XPATH_EXPR_ERROR);
++ }
+ buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
+ if (buffer == NULL) {
+ XP_ERRORNULL(XPATH_MEMORY_ERROR);
+@@ -9939,6 +9939,9 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
+ (IS_COMBINING(c)) ||
+ (IS_EXTENDER(c))) {
+ if (len + 10 > max) {
++ if (max > XML_MAX_NAME_LENGTH) {
++ XP_ERRORNULL(XPATH_EXPR_ERROR);
++ }
+ max *= 2;
+ buffer = (xmlChar *) xmlRealloc(buffer,
+ max * sizeof(xmlChar));
+--
+1.7.11.4
+
diff --git a/libxml2-Impose-a-reasonable-limit-on-PI-size.patch b/libxml2-Impose-a-reasonable-limit-on-PI-size.patch
new file mode 100644
index 0000000..35ce9d9
--- /dev/null
+++ b/libxml2-Impose-a-reasonable-limit-on-PI-size.patch
@@ -0,0 +1,82 @@
+From 145a79c9427d526758ef45caa6daa9ddb229af7d Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Thu, 19 Jul 2012 20:34:26 +0800
+Subject: [PATCH] Impose a reasonable limit on PI size
+To: libvir-list at redhat.com
+
+Unless the XML_PARSE_HUGE option is given to the parser,
+the value is XML_MAX_TEXT_LENGTH, i.e. the same than for a
+text node within content.
+Also cleanup some unsigned int used for memory size.
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 26 +++++++++++++++++++++-----
+ 1 file changed, 21 insertions(+), 5 deletions(-)
+
+diff --git a/parser.c b/parser.c
+index 7e5cef7..a78b0b1 100644
+--- a/parser.c
++++ b/parser.c
+@@ -4953,8 +4953,8 @@ error:
+ void
+ xmlParsePI(xmlParserCtxtPtr ctxt) {
+ xmlChar *buf = NULL;
+- int len = 0;
+- int size = XML_PARSER_BUFFER_SIZE;
++ size_t len = 0;
++ size_t size = XML_PARSER_BUFFER_SIZE;
+ int cur, l;
+ const xmlChar *target;
+ xmlParserInputState state;
+@@ -5011,9 +5011,8 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
+ ((cur != '?') || (NXT(1) != '>'))) {
+ if (len + 5 >= size) {
+ xmlChar *tmp;
+-
+- size *= 2;
+- tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
++ size_t new_size = size * 2;
++ tmp = (xmlChar *) xmlRealloc(buf, new_size);
+ if (tmp == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ xmlFree(buf);
+@@ -5021,11 +5020,20 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
+ return;
+ }
+ buf = tmp;
++ size = new_size;
+ }
+ count++;
+ if (count > 50) {
+ GROW;
+ count = 0;
++ if ((len > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
++ "PI %s too big found", target);
++ xmlFree(buf);
++ ctxt->instate = state;
++ return;
++ }
+ }
+ COPY_BUF(l,buf,len,cur);
+ NEXTL(l);
+@@ -5036,6 +5044,14 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
+ cur = CUR_CHAR(l);
+ }
+ }
++ if ((len > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
++ "PI %s too big found", target);
++ xmlFree(buf);
++ ctxt->instate = state;
++ return;
++ }
+ buf[len] = 0;
+ if (cur != '?') {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
+--
+1.7.11.4
+
diff --git a/libxml2-Impose-a-reasonable-limit-on-attribute-size.patch b/libxml2-Impose-a-reasonable-limit-on-attribute-size.patch
new file mode 100644
index 0000000..9dbd823
--- /dev/null
+++ b/libxml2-Impose-a-reasonable-limit-on-attribute-size.patch
@@ -0,0 +1,110 @@
+From f0aec06ab836ab85cf925f0f8459c95a58e2d67b Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Thu, 19 Jul 2012 11:25:16 +0800
+Subject: [PATCH] Impose a reasonable limit on attribute size
+To: libvir-list at redhat.com
+
+Unless the XML_PARSE_HUGE option is given to the parser,
+the value is XML_MAX_TEXT_LENGTH, i.e. the same than for a
+text node within content.
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 48 insertions(+), 2 deletions(-)
+
+diff --git a/parser.c b/parser.c
+index 4303527..fb5cb72 100644
+--- a/parser.c
++++ b/parser.c
+@@ -3788,6 +3788,16 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
+ c = CUR_CHAR(l);
+ while ((NXT(0) != limit) && /* checked */
+ (IS_CHAR(c)) && (c != '<')) {
++ /*
++ * Impose a reasonable limit on attribute size, unless XML_PARSE_HUGE
++ * special option is given
++ */
++ if ((len > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
++ "AttValue lenght too long\n");
++ goto mem_error;
++ }
+ if (c == 0) break;
+ if (c == '&') {
+ in_space = 0;
+@@ -8649,6 +8659,12 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
+ in = in + delta;
+ }
+ end = ctxt->input->end;
++ if (((in - start) > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
++ "AttValue lenght too long\n");
++ return(NULL);
++ }
+ }
+ }
+ while ((in < end) && (*in != limit) && (*in >= 0x20) &&
+@@ -8663,6 +8679,12 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
+ in = in + delta;
+ }
+ end = ctxt->input->end;
++ if (((in - start) > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
++ "AttValue lenght too long\n");
++ return(NULL);
++ }
+ }
+ }
+ last = in;
+@@ -8684,8 +8706,20 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
+ last = last + delta;
+ }
+ end = ctxt->input->end;
+- }
+- }
++ if (((in - start) > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
++ "AttValue lenght too long\n");
++ return(NULL);
++ }
++ }
++ }
++ if (((in - start) > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
++ "AttValue lenght too long\n");
++ return(NULL);
++ }
+ if (*in != limit) goto need_complex;
+ } else {
+ while ((in < end) && (*in != limit) && (*in >= 0x20) &&
+@@ -8700,9 +8734,21 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
+ in = in + delta;
+ }
+ end = ctxt->input->end;
++ if (((in - start) > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
++ "AttValue lenght too long\n");
++ return(NULL);
++ }
+ }
+ }
+ last = in;
++ if (((in - start) > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
++ "AttValue lenght too long\n");
++ return(NULL);
++ }
+ if (*in != limit) goto need_complex;
+ }
+ in++;
+--
+1.7.11.4
+
diff --git a/libxml2-Impose-a-reasonable-limit-on-comment-size.patch b/libxml2-Impose-a-reasonable-limit-on-comment-size.patch
new file mode 100644
index 0000000..d52d95f
--- /dev/null
+++ b/libxml2-Impose-a-reasonable-limit-on-comment-size.patch
@@ -0,0 +1,97 @@
+From e3127872a59348cd637c8236aa2c2bad7f5ae439 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Thu, 19 Jul 2012 11:58:47 +0800
+Subject: [PATCH] Impose a reasonable limit on comment size
+To: libvir-list at redhat.com
+
+Unless the XML_PARSE_HUGE option is given to the parser,
+the value is XML_MAX_TEXT_LENGTH, i.e. the same than for a
+text node within content.
+Also cleanup some unsigned int used for memory size.
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 33 ++++++++++++++++++++++++++-------
+ 1 file changed, 26 insertions(+), 7 deletions(-)
+
+diff --git a/parser.c b/parser.c
+index fb5cb72..7e5cef7 100644
+--- a/parser.c
++++ b/parser.c
+@@ -4549,11 +4549,12 @@ xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
+ * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
+ */
+ static void
+-xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, int len, int size) {
++xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
++ size_t len, size_t size) {
+ int q, ql;
+ int r, rl;
+ int cur, l;
+- int count = 0;
++ size_t count = 0;
+ int inputid;
+
+ inputid = ctxt->input->id;
+@@ -4599,16 +4600,26 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, int len, int size) {
+ if ((r == '-') && (q == '-')) {
+ xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
+ }
++ if ((len > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
++ "Comment too big found", NULL);
++ xmlFree (buf);
++ return;
++ }
+ if (len + 5 >= size) {
+ xmlChar *new_buf;
+- size *= 2;
+- new_buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
++ size_t new_size;
++
++ new_size = size * 2;
++ new_buf = (xmlChar *) xmlRealloc(buf, new_size);
+ if (new_buf == NULL) {
+ xmlFree (buf);
+ xmlErrMemory(ctxt, NULL);
+ return;
+ }
+ buf = new_buf;
++ size = new_size;
+ }
+ COPY_BUF(ql,buf,len,q);
+ q = r;
+@@ -4669,11 +4680,12 @@ not_terminated:
+ void
+ xmlParseComment(xmlParserCtxtPtr ctxt) {
+ xmlChar *buf = NULL;
+- int size = XML_PARSER_BUFFER_SIZE;
+- int len = 0;
++ size_t size = XML_PARSER_BUFFER_SIZE;
++ size_t len = 0;
+ xmlParserInputState state;
+ const xmlChar *in;
+- int nbchar = 0, ccol;
++ size_t nbchar = 0;
++ int ccol;
+ int inputid;
+
+ /*
+@@ -4753,6 +4765,13 @@ get_more:
+ buf[len] = 0;
+ }
+ }
++ if ((len > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
++ "Comment too big found", NULL);
++ xmlFree (buf);
++ return;
++ }
+ ctxt->input->cur = in;
+ if (*in == 0xA) {
+ in++;
+--
+1.7.11.4
+
diff --git a/libxml2-Introduce-some-default-parser-limits.patch b/libxml2-Introduce-some-default-parser-limits.patch
new file mode 100644
index 0000000..b6b9566
--- /dev/null
+++ b/libxml2-Introduce-some-default-parser-limits.patch
@@ -0,0 +1,310 @@
+From b7e7e2b1d1975f400d6c81eb6c4ad6c683562ca3 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Mon, 30 Jul 2012 10:08:45 +0800
+Subject: [PATCH] Introduce some default parser limits
+To: libvir-list at redhat.com
+
+Those can be overrided by the XML_PARSE_HUGE option, they
+are just default limits for Name lenght, dictionary size limits
+and maximum amount of parser lookup.
+* include/libxml/parserInternals.h: define the limits
+* include/libxml/xmlerror.h: add a new error
+* parser.c parserInternals.c: implements the new limits
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ include/libxml/parserInternals.h | 35 ++++++++++++++++-
+ include/libxml/xmlerror.h | 1 +
+ parser.c | 84 ++++++++++++++++++++++++++++++++++++++--
+ parserInternals.c | 2 +
+ 4 files changed, 118 insertions(+), 4 deletions(-)
+
+diff --git a/include/libxml/parserInternals.h b/include/libxml/parserInternals.h
+index a5e75b5..d6dcb26 100644
+--- a/include/libxml/parserInternals.h
++++ b/include/libxml/parserInternals.h
+@@ -1,5 +1,5 @@
+ /*
+- * Summary: internals routines exported by the parser.
++ * Summary: internals routines and limits exported by the parser.
+ * Description: this module exports a number of internal parsing routines
+ * they are not really all intended for applications but
+ * can prove useful doing low level processing.
+@@ -36,10 +36,43 @@ XMLPUBVAR unsigned int xmlParserMaxDepth;
+ * Maximum size allowed for a single text node when building a tree.
+ * This is not a limitation of the parser but a safety boundary feature,
+ * use XML_PARSE_HUGE option to override it.
++ * Introduced in 2.9.0
+ */
+ #define XML_MAX_TEXT_LENGTH 10000000
+
+ /**
++ * XML_MAX_NAME_LENGTH:
++ *
++ * Maximum size allowed for a markup identitier
++ * This is not a limitation of the parser but a safety boundary feature,
++ * use XML_PARSE_HUGE option to override it.
++ * Note that with the use of parsing dictionaries overriding the limit
++ * may result in more runtime memory usage in face of "unfriendly' content
++ * Introduced in 2.9.0
++ */
++#define XML_MAX_NAME_LENGTH 50000
++
++/**
++ * XML_MAX_DICTIONARY_LIMIT:
++ *
++ * Maximum size allowed by the parser for a dictionary by default
++ * This is not a limitation of the parser but a safety boundary feature,
++ * use XML_PARSE_HUGE option to override it.
++ * Introduced in 2.9.0
++ */
++#define XML_MAX_DICTIONARY_LIMIT 10000000
++
++/**
++ * XML_MAX_LOOKUP_LIMIT:
++ *
++ * Maximum size allowed by the parser for ahead lookup
++ * This is an upper boundary enforced by the parser to avoid bad
++ * behaviour on "unfriendly' content
++ * Introduced in 2.9.0
++ */
++#define XML_MAX_LOOKUP_LIMIT 10000000
++
++/**
+ * XML_MAX_NAMELEN:
+ *
+ * Identifiers can be longer, but this will be more costly
+diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h
+index e924211..b5e8c77 100644
+--- a/include/libxml/xmlerror.h
++++ b/include/libxml/xmlerror.h
+@@ -205,6 +205,7 @@ typedef enum {
+ XML_WAR_ENTITY_REDEFINED, /* 107 */
+ XML_ERR_UNKNOWN_VERSION, /* 108 */
+ XML_ERR_VERSION_MISMATCH, /* 109 */
++ XML_ERR_NAME_TOO_LONG, /* 110 */
+ XML_NS_ERR_XML_NAMESPACE = 200,
+ XML_NS_ERR_UNDEFINED_NAMESPACE, /* 201 */
+ XML_NS_ERR_QNAME, /* 202 */
+diff --git a/parser.c b/parser.c
+index a78b0b1..b54fbc4 100644
+--- a/parser.c
++++ b/parser.c
+@@ -457,6 +457,9 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
+ case XML_ERR_VERSION_MISSING:
+ errmsg = "Malformed declaration expecting version\n";
+ break;
++ case XML_ERR_NAME_TOO_LONG:
++ errmsg = "Name too long use XML_PARSE_HUGE option\n";
++ break;
+ #if 0
+ case:
+ errmsg = "\n";
+@@ -1992,6 +1995,11 @@ static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
+ xmlGROW (ctxt);
+
+ static void xmlGROW (xmlParserCtxtPtr ctxt) {
++ if ((((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
++ ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
++ }
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+ if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
+ (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
+@@ -3250,6 +3258,11 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
+ c = CUR_CHAR(l);
+ }
+ }
++ if ((len > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
++ return(NULL);
++ }
+ if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
+ return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
+ return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
+@@ -3299,6 +3312,11 @@ xmlParseName(xmlParserCtxtPtr ctxt) {
+ in++;
+ if ((*in > 0) && (*in < 0x80)) {
+ count = in - ctxt->input->cur;
++ if ((count > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
++ return(NULL);
++ }
+ ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
+ ctxt->input->cur = in;
+ ctxt->nbChars += count;
+@@ -3335,6 +3353,11 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
+ while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
+ (xmlIsNameChar(ctxt, c) && (c != ':'))) {
+ if (count++ > 100) {
++ if ((len > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
++ return(NULL);
++ }
+ count = 0;
+ GROW;
+ }
+@@ -3342,6 +3365,11 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
+ NEXTL(l);
+ c = CUR_CHAR(l);
+ }
++ if ((len > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
++ return(NULL);
++ }
+ return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
+ }
+
+@@ -3386,6 +3414,11 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) {
+ in++;
+ if ((*in > 0) && (*in < 0x80)) {
+ count = in - ctxt->input->cur;
++ if ((count > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
++ return(NULL);
++ }
+ ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
+ ctxt->input->cur = in;
+ ctxt->nbChars += count;
+@@ -3496,6 +3529,13 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
+ while (xmlIsNameChar(ctxt, c)) {
+ if (len + 10 > max) {
+ xmlChar *tmp;
++
++ if ((len > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
++ xmlFree(buffer);
++ return(NULL);
++ }
+ max *= 2;
+ tmp = (xmlChar *) xmlRealloc(buffer,
+ max * sizeof(xmlChar));
+@@ -3515,6 +3555,11 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
+ return(buffer);
+ }
+ }
++ if ((len > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
++ return(NULL);
++ }
+ *str = cur;
+ return(xmlStrndup(buf, len));
+ }
+@@ -3576,6 +3621,12 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
+ if (len + 10 > max) {
+ xmlChar *tmp;
+
++ if ((max > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
++ xmlFree(buffer);
++ return(NULL);
++ }
+ max *= 2;
+ tmp = (xmlChar *) xmlRealloc(buffer,
+ max * sizeof(xmlChar));
+@@ -3596,6 +3647,11 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
+ }
+ if (len == 0)
+ return(NULL);
++ if ((len > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
++ return(NULL);
++ }
+ return(xmlStrndup(buf, len));
+ }
+
+@@ -4055,6 +4111,13 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
+ if (len + 5 >= size) {
+ xmlChar *tmp;
+
++ if ((size > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
++ xmlFree(buf);
++ ctxt->instate = (xmlParserInputState) state;
++ return(NULL);
++ }
+ size *= 2;
+ tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+ if (tmp == NULL) {
+@@ -4132,6 +4195,12 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
+ if (len + 1 >= size) {
+ xmlChar *tmp;
+
++ if ((size > XML_MAX_NAME_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
++ xmlFree(buf);
++ return(NULL);
++ }
+ size *= 2;
+ tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+ if (tmp == NULL) {
+@@ -8322,7 +8391,7 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
+ xmlFree(attvalue);
+ }
+
+-failed:
++failed:
+
+ GROW
+ if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
+@@ -9507,14 +9576,21 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
+ if (len + 5 >= size) {
+ xmlChar *tmp;
+
+- size *= 2;
+- tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
++ if ((size > XML_MAX_TEXT_LENGTH) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
++ "CData section too big found", NULL);
++ xmlFree (buf);
++ return;
++ }
++ tmp = (xmlChar *) xmlRealloc(buf, size * 2 * sizeof(xmlChar));
+ if (tmp == NULL) {
+ xmlFree(buf);
+ xmlErrMemory(ctxt, NULL);
+ return;
+ }
+ buf = tmp;
++ size *= 2;
+ }
+ COPY_BUF(rl,buf,len,r);
+ r = s;
+@@ -14663,6 +14739,8 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi
+ if (options & XML_PARSE_HUGE) {
+ ctxt->options |= XML_PARSE_HUGE;
+ options -= XML_PARSE_HUGE;
++ if (ctxt->dict != NULL)
++ xmlDictSetLimit(ctxt->dict, 0);
+ }
+ if (options & XML_PARSE_OLDSAX) {
+ ctxt->options |= XML_PARSE_OLDSAX;
+diff --git a/parserInternals.c b/parserInternals.c
+index 2404ddf..5e5d06a 100644
+--- a/parserInternals.c
++++ b/parserInternals.c
+@@ -1618,6 +1618,8 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
+ xmlErrMemory(NULL, "cannot initialize parser context\n");
+ return(-1);
+ }
++ xmlDictSetLimit(ctxt->dict, XML_MAX_DICTIONARY_LIMIT);
++
+ if (ctxt->sax == NULL)
+ ctxt->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
+ if (ctxt->sax == NULL) {
+--
+1.7.11.4
+
diff --git a/libxml2-Make-sure-the-parser-returns-when-getting-a-Stop-order.patch b/libxml2-Make-sure-the-parser-returns-when-getting-a-Stop-order.patch
new file mode 100644
index 0000000..9236096
--- /dev/null
+++ b/libxml2-Make-sure-the-parser-returns-when-getting-a-Stop-order.patch
@@ -0,0 +1,69 @@
+From 4fc9f5dafff28ead4a75ba1bcb10feaea8370a3b Mon Sep 17 00:00:00 2001
+From: Chris Evans <scarybeasts at gmail.com>
+Date: Wed, 14 Dec 2011 16:18:25 +0800
+Subject: [PATCH] Make sure the parser returns when getting a Stop order
+To: libvir-list at redhat.com
+
+patch backported from chromiun bug fixes, assuming author is Chris
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/parser.c b/parser.c
+index d1c7888..ef00f42 100644
+--- a/parser.c
++++ b/parser.c
+@@ -4949,7 +4949,8 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
+ (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 +5030,8 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
+ }
+- ctxt->instate = state;
++ if (ctxt->instate != XML_PARSER_EOF)
++ ctxt->instate = state;
+ }
+ }
+
+@@ -9588,6 +9590,8 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
+ else
+ name = xmlParseStartTag(ctxt);
+ #endif /* LIBXML_SAX1_ENABLED */
++ if (ctxt->instate == XML_PARSER_EOF)
++ return;
+ if (name == NULL) {
+ spacePop(ctxt);
+ return;
+@@ -10967,6 +10971,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ 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 +11159,9 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ 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;
+--
+1.7.11.4
+
diff --git a/libxml2-More-avoid-quadratic-behaviour.patch b/libxml2-More-avoid-quadratic-behaviour.patch
new file mode 100644
index 0000000..b2c3f75
--- /dev/null
+++ b/libxml2-More-avoid-quadratic-behaviour.patch
@@ -0,0 +1,102 @@
+From a2e984b7fb4c62ed67a9a142c46498be507849cf Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Thu, 19 Jul 2012 20:36:25 +0800
+Subject: [PATCH] More avoid quadratic behaviour
+To: libvir-list at redhat.com
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 28 ++++++++++++++++++++++++----
+ 1 file changed, 24 insertions(+), 4 deletions(-)
+
+diff --git a/parser.c b/parser.c
+index 0bb4591..8cb316c 100644
+--- a/parser.c
++++ b/parser.c
+@@ -11319,9 +11319,13 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ break;
+ } else if ((cur == '<') && (next == '?')) {
+ if ((!terminate) &&
+- (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
++ (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
++ ctxt->progressive = XML_PARSER_PI;
+ goto done;
++ }
+ xmlParsePI(ctxt);
++ ctxt->instate = XML_PARSER_CONTENT;
++ ctxt->progressive = 1;
+ } else if ((cur == '<') && (next != '!')) {
+ ctxt->instate = XML_PARSER_START_TAG;
+ break;
+@@ -11520,13 +11524,17 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ next = ctxt->input->cur[1];
+ if ((cur == '<') && (next == '?')) {
+ if ((!terminate) &&
+- (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
++ (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
++ ctxt->progressive = XML_PARSER_PI;
+ goto done;
++ }
+ #ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing PI\n");
+ #endif
+ xmlParsePI(ctxt);
++ ctxt->instate = XML_PARSER_MISC;
++ ctxt->progressive = 1;
+ ctxt->checkIndex = 0;
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == '-') &&
+@@ -11610,13 +11618,17 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ next = ctxt->input->cur[1];
+ if ((cur == '<') && (next == '?')) {
+ if ((!terminate) &&
+- (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
++ (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
++ ctxt->progressive = XML_PARSER_PI;
+ goto done;
++ }
+ #ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing PI\n");
+ #endif
+ xmlParsePI(ctxt);
++ ctxt->instate = XML_PARSER_PROLOG;
++ ctxt->progressive = 1;
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
+ if ((!terminate) &&
+@@ -11657,14 +11669,17 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ next = ctxt->input->cur[1];
+ if ((cur == '<') && (next == '?')) {
+ if ((!terminate) &&
+- (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
++ (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
++ ctxt->progressive = XML_PARSER_PI;
+ goto done;
++ }
+ #ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing PI\n");
+ #endif
+ xmlParsePI(ctxt);
+ ctxt->instate = XML_PARSER_EPILOG;
++ ctxt->progressive = 1;
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
+ if ((!terminate) &&
+@@ -11939,6 +11954,11 @@ xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
+ return(1);
+ return(0);
+ }
++ if (ctxt->progressive == XML_PARSER_PI) {
++ if (memchr(chunk, '>', size) != NULL)
++ return(1);
++ return(0);
++ }
+ return(1);
+ }
+
+--
+1.7.11.4
+
diff --git a/libxml2-More-fixups-on-the-push-parser-behaviour.patch b/libxml2-More-fixups-on-the-push-parser-behaviour.patch
new file mode 100644
index 0000000..ee42f19
--- /dev/null
+++ b/libxml2-More-fixups-on-the-push-parser-behaviour.patch
@@ -0,0 +1,62 @@
+From 17c73f2e605322aad492b670123a6939f7706f88 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Fri, 3 Aug 2012 12:03:31 +0800
+Subject: [PATCH] More fixups on the push parser behaviour
+To: libvir-list at redhat.com
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/parser.c b/parser.c
+index f4ddc5b..6a9e54d 100644
+--- a/parser.c
++++ b/parser.c
+@@ -11561,13 +11561,17 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ (ctxt->input->cur[7] == 'P') &&
+ (ctxt->input->cur[8] == 'E')) {
+ if ((!terminate) &&
+- (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
++ (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0)) {
++ ctxt->progressive = XML_PARSER_DTD;
+ goto done;
++ }
+ #ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing internal subset\n");
+ #endif
+ ctxt->inSubset = 1;
++ ctxt->progressive = 1;
++ ctxt->checkIndex = 0;
+ xmlParseDocTypeDecl(ctxt);
+ if (RAW == '[') {
+ ctxt->instate = XML_PARSER_DTD;
+@@ -11959,12 +11963,23 @@ xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
+ return(1);
+ return(0);
+ }
++ if (ctxt->instate == XML_PARSER_CDATA_SECTION) {
++ if (memchr(chunk, '>', size) != NULL)
++ return(1);
++ return(0);
++ }
+ if (ctxt->progressive == XML_PARSER_PI) {
+ if (memchr(chunk, '>', size) != NULL)
+ return(1);
+ return(0);
+ }
+- if (ctxt->instate == XML_PARSER_DTD) {
++ if (ctxt->instate == XML_PARSER_END_TAG) {
++ if (memchr(chunk, '>', size) != NULL)
++ return(1);
++ return(0);
++ }
++ if ((ctxt->progressive == XML_PARSER_DTD) ||
++ (ctxt->instate == XML_PARSER_DTD)) {
+ if (memchr(chunk, ']', size) != NULL)
+ return(1);
+ return(0);
+--
+1.7.11.4
+
diff --git a/libxml2-Multilib-fix.patch b/libxml2-Multilib-fix.patch
new file mode 100644
index 0000000..d9d929c
--- /dev/null
+++ b/libxml2-Multilib-fix.patch
@@ -0,0 +1,34 @@
+From 02f33764685acb0f9b79d80a1fbe2e0830dac5ed Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Tue, 21 Aug 2012 11:59:03 +0800
+Subject: [PATCH] Multilib fix
+To: libvir-list at redhat.com
+
+Only for RHEL/Fedora
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ xml2-config.in | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/xml2-config.in b/xml2-config.in
+index 2989325..f65b54d 100644
+--- a/xml2-config.in
++++ b/xml2-config.in
+@@ -3,7 +3,12 @@
+ prefix=@prefix@
+ exec_prefix=@exec_prefix@
+ includedir=@includedir@
+-libdir=@libdir@
++if [ "`ldd /bin/sh | grep lib64`" = "" ]
++then
++ libdir=${exec_prefix}/lib
++else
++ libdir=${exec_prefix}/lib64
++fi
+
+ usage()
+ {
+--
+1.7.11.4
+
diff --git a/libxml2-Reactivate-the-shared-library-versionning-script.patch b/libxml2-Reactivate-the-shared-library-versionning-script.patch
new file mode 100644
index 0000000..ab993d1
--- /dev/null
+++ b/libxml2-Reactivate-the-shared-library-versionning-script.patch
@@ -0,0 +1,27 @@
+From 5dcf504e12ce0404d0fc6a981b16af9c8c2ad6e8 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Thu, 4 Nov 2010 21:53:14 +0100
+Subject: [PATCH] Reactivate the shared library versionning script
+To: libvir-list at redhat.com
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ configure.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure.in b/configure.in
+index 59d0629..a1d2c89 100644
+--- a/configure.in
++++ b/configure.in
+@@ -84,7 +84,7 @@ else
+ esac
+ fi
+ AC_SUBST(VERSION_SCRIPT_FLAGS)
+-AM_CONDITIONAL([USE_VERSION_SCRIPT], [test -z "$VERSION_SCRIPT_FLAGS"])
++AM_CONDITIONAL([USE_VERSION_SCRIPT], [test -n "$VERSION_SCRIPT_FLAGS"])
+
+ dnl
+ dnl We process the AC_ARG_WITH first so that later we can modify
+--
+1.7.11.4
+
diff --git a/libxml2-Small-fix-for-previous-commit.patch b/libxml2-Small-fix-for-previous-commit.patch
new file mode 100644
index 0000000..66ed59b
--- /dev/null
+++ b/libxml2-Small-fix-for-previous-commit.patch
@@ -0,0 +1,34 @@
+From f7ec29239b66123c29d84f810070c23855061d3f Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Thu, 18 Nov 2010 11:07:24 +0100
+Subject: [PATCH] Small fix for previous commit
+To: libvir-list at redhat.com
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ xpath.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/xpath.c b/xpath.c
+index 5474849..eef69f7 100644
+--- a/xpath.c
++++ b/xpath.c
+@@ -11765,13 +11765,14 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
+ xmlXPathObjectPtr tmp;
+ /* pop the result if any */
+ tmp = valuePop(ctxt);
+- if (tmp != contextObj)
++ if (tmp != contextObj) {
+ /*
+ * Free up the result
+ * then pop off contextObj, which will be freed later
+ */
+ xmlXPathReleaseObject(xpctxt, tmp);
+ valuePop(ctxt);
++ }
+ goto evaluation_error;
+ }
+
+--
+1.7.11.4
+
diff --git a/libxml2-Strengthen-behaviour-of-the-push-parser-in-problematic-situations.patch b/libxml2-Strengthen-behaviour-of-the-push-parser-in-problematic-situations.patch
new file mode 100644
index 0000000..cdbe414
--- /dev/null
+++ b/libxml2-Strengthen-behaviour-of-the-push-parser-in-problematic-situations.patch
@@ -0,0 +1,71 @@
+From 3bb06661c6e9bf29df03dfb85b121cb195481887 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Tue, 31 Jul 2012 10:53:47 +0800
+Subject: [PATCH] Strengthen behaviour of the push parser in problematic
+ situations
+To: libvir-list at redhat.com
+
+Implement the maximum lookahead stategy, and fix some handling
+of DTD to speed up processing.
+
+Conflicts:
+ parser.c: a bit of surgery was needed to get that patch to
+ apply and work in a 2.7.6 context
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ parser.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/parser.c b/parser.c
+index 8cb316c..f4ddc5b 100644
+--- a/parser.c
++++ b/parser.c
+@@ -11812,6 +11812,10 @@ not_end_of_int_subset:
+ /*
+ * We didn't found the end of the Internal subset
+ */
++ if (quote == 0)
++ ctxt->checkIndex = base;
++ else
++ ctxt->checkIndex = 0;
+ #ifdef DEBUG_PUSH
+ if (next == 0)
+ xmlGenericError(xmlGenericErrorContext,
+@@ -11820,6 +11824,7 @@ not_end_of_int_subset:
+ goto done;
+
+ found_end_int_subset:
++ ctxt->checkIndex = 0;
+ xmlParseInternalSubset(ctxt);
+ ctxt->inSubset = 2;
+ if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
+@@ -11959,6 +11964,11 @@ xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
+ return(1);
+ return(0);
+ }
++ if (ctxt->instate == XML_PARSER_DTD) {
++ if (memchr(chunk, ']', size) != NULL)
++ return(1);
++ return(0);
++ }
+ return(1);
+ }
+
+@@ -12088,6 +12098,13 @@ xmldecl_done:
+ avail - old_avail)))
+ xmlParseTryOrFinish(ctxt, terminate);
+ }
++ if ((ctxt->input != NULL) &&
++ (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
++ ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
++ ((ctxt->options & XML_PARSE_HUGE) == 0)) {
++ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
++ ctxt->instate = XML_PARSER_EOF;
++ }
+ if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+ return(ctxt->errNo);
+
+--
+1.7.11.4
+
diff --git a/libxml2-force-randomization-of-dict-and-hash.patch b/libxml2-force-randomization-of-dict-and-hash.patch
new file mode 100644
index 0000000..d614f6d
--- /dev/null
+++ b/libxml2-force-randomization-of-dict-and-hash.patch
@@ -0,0 +1,45 @@
+From 297c2c5ec7ac8766b626e41b9e15537e01cace22 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veillard at redhat.com>
+Date: Tue, 21 Aug 2012 12:11:33 +0800
+Subject: [PATCH] force randomization of dict and hash
+To: libvir-list at redhat.com
+
+Force randomization even if configure wasn't regenerated
+
+Signed-off-by: Daniel Veillard <veillard at redhat.com>
+---
+ dict.c | 3 +++
+ hash.c | 3 +++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/dict.c b/dict.c
+index d73d230..bd64afb 100644
+--- a/dict.c
++++ b/dict.c
+@@ -26,6 +26,9 @@
+ #include <time.h>
+ #endif
+
++/* Force randomization even if configure wasn't regenerated */
++#define DICT_RANDOMIZATION
++
+ /*
+ * Following http://www.ocert.org/advisories/ocert-2011-003.html
+ * it seems that having hash randomization might be a good idea
+diff --git a/hash.c b/hash.c
+index 02e01fb..ba36e15 100644
+--- a/hash.c
++++ b/hash.c
+@@ -28,6 +28,9 @@
+ #include <time.h>
+ #endif
+
++/* Force randomization even if configure wasn't regenerated */
++#define HASH_RANDOMIZATION
++
+ /*
+ * Following http://www.ocert.org/advisories/ocert-2011-003.html
+ * it seems that having hash randomization might be a good idea
+--
+1.7.11.4
+
diff --git a/libxml2.spec b/libxml2.spec
index 7856c13..ae8049a 100644
--- a/libxml2.spec
+++ b/libxml2.spec
@@ -1,16 +1,47 @@
Summary: Library providing XML and HTML support
Name: libxml2
Version: 2.7.8
-Release: 7%{?dist}%{?extra_release}
+Release: 8%{?dist}%{?extra_release}
License: MIT
Group: Development/Libraries
Source: ftp://xmlsoft.org/libxml2/libxml2-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-root
BuildRequires: python python-devel zlib-devel pkgconfig
URL: http://xmlsoft.org/
-Patch0: libxml2-multilib.patch
-Patch1: libxml2-2.7.8-reactivate-versionning-script.patch
-Patch2: libxml2-2.7.7-xpath-double-free.patch
+Patch0: libxml2-Multilib-fix.patch
+Patch1: libxml2-Reactivate-the-shared-library-versionning-script.patch
+Patch2: libxml2-Fix-a-potential-freeing-error-in-XPath.patch
+Patch3: libxml2-Small-fix-for-previous-commit.patch
+Patch4: libxml2-Fix-some-potential-problems-on-reallocation-failures.patch
+Patch5: libxml2-Hardening-of-XPath-evaluation.patch
+Patch6: libxml2-Fix-an-off-by-one-error-in-encoding.patch
+Patch7: libxml2-Fix-missing-error-status-in-XPath-evaluation.patch
+Patch8: libxml2-Make-sure-the-parser-returns-when-getting-a-Stop-order.patch
+Patch9: libxml2-Fix-an-allocation-error-when-copying-entities.patch
+Patch10: libxml2-Add-hash-randomization-to-hash-and-dict-structures.patch
+Patch11: libxml2-force-randomization-of-dict-and-hash.patch
+Patch12: libxml2-Fix-a-failure-to-report-xmlreader-parsing-failures.patch
+Patch13: libxml2-Fix-parser-local-buffers-size-problems.patch
+Patch14: libxml2-Fix-entities-local-buffers-size-problems.patch
+Patch15: libxml2-Fix-an-error-in-previous-commit.patch
+Patch16: libxml2-Do-not-fetch-external-parsed-entities.patch
+Patch17: libxml2-Impose-a-reasonable-limit-on-attribute-size.patch
+Patch18: libxml2-Impose-a-reasonable-limit-on-comment-size.patch
+Patch19: libxml2-Impose-a-reasonable-limit-on-PI-size.patch
+Patch20: libxml2-Cleanups-and-new-limit-APIs-for-dictionaries.patch
+Patch21: libxml2-Introduce-some-default-parser-limits.patch
+Patch22: libxml2-Implement-some-default-limits-in-the-XPath-module.patch
+Patch23: libxml2-Fixup-limits-parser.patch
+Patch24: libxml2-Enforce-XML_PARSER_EOF-state-handling-through-the-parser.patch
+Patch25: libxml2-Avoid-quadratic-behaviour-in-some-push-parsing-cases.patch
+Patch26: libxml2-More-avoid-quadratic-behaviour.patch
+Patch27: libxml2-Strengthen-behaviour-of-the-push-parser-in-problematic-situations.patch
+Patch28: libxml2-More-fixups-on-the-push-parser-behaviour.patch
+Patch29: libxml2-Fix-a-segfault-on-XSD-validation-on-pattern-error.patch
+Patch30: libxml2-Fix-an-unimplemented-part-in-RNG-value-validation.patch
+Patch31: libxml2-Fix-an-off-by-one-pointer-access.patch
+Patch32: libxml2-Change-the-XPath-code-to-percolate-allocation-errors.patch
+
%description
This library allows to manipulate XML files. It includes support
@@ -71,6 +102,36 @@ at parse time or later once the document has been modified.
%patch0 -p1
%patch1 -p1
%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
+%patch21 -p1
+%patch22 -p1
+%patch23 -p1
+%patch24 -p1
+%patch25 -p1
+%patch26 -p1
+%patch27 -p1
+%patch28 -p1
+%patch29 -p1
+%patch30 -p1
+%patch31 -p1
+%patch32 -p1
%build
%configure
@@ -145,6 +206,44 @@ rm -fr %{buildroot}
%doc doc/python.html
%changelog
+* Mon Sep 10 2012 Daniel Veillard <veillard at redhat.com> - 2.7.8-8
+- Fixes for CVE-2011-3919 CVE-2011-3905 CVE-2011-2834 (rhbz#772122)
+- Fixes for CVE-2012-2807 (843743)
+- Fixes for CVE-2012-0841 (795698)
+- Fix for CVE-2011-1944 (709750)
+- Fix for CVE-2011-0216 (755813)
+- Fix for CVE-2011-2821 (735715)
+- Fix for CVE-2011-3102 (822171)
+- Fix some potential problems on reallocation failures
+- Hardening of XPath evaluation
+- Fix an off by one error in encoding
+- Fix missing error status in XPath evaluation
+- Make sure the parser returns when getting a Stop order
+- Fix an allocation error when copying entities
+- Add hash randomization to hash and dict structures
+- Force randomization of dict and hash
+- Fix a failure to report xmlreader parsing failures
+- Fix parser local buffers size problems
+- Fix entities local buffers size problems
+- Fix an error in previous commit
+- Do not fetch external parsed entities
+- Impose a reasonable limit on attribute size
+- Impose a reasonable limit on comment size
+- Impose a reasonable limit on PI size
+- Cleanups and new limit APIs for dictionaries
+- Introduce some default parser limits
+- Implement some default limits in the XPath module
+- Fixup limits parser
+- Enforce XML_PARSER_EOF state handling through the parser
+- Avoid quadratic behaviour in some push parsing cases
+- More avoid quadratic behaviour
+- Strengthen behaviour of the push parser in problematic situations
+- More fixups on the push parser behaviour
+- Fix a segfault on XSD validation on pattern error
+- Fix an unimplemented part in RNG value validation
+- Fix an off by one pointer access
+- Change the XPath code to percolate allocation errors
+
* Fri Jan 13 2012 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 2.7.8-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
More information about the scm-commits
mailing list