Blame SOURCES/libxml2-CVE-2015-1819-Enforce-the-reader-to-run-in-constant-memory.patch

6dedca
From 5cec67e3f8d56e6e5fda2f90e102950cbb09e3d1 Mon Sep 17 00:00:00 2001
6dedca
From: Daniel Veillard <veillard@redhat.com>
6dedca
Date: Tue, 14 Apr 2015 17:41:48 +0800
6dedca
Subject: [PATCH] CVE-2015-1819 Enforce the reader to run in constant memory
6dedca
To: libvir-list@redhat.com
6dedca
6dedca
One of the operation on the reader could resolve entities
6dedca
leading to the classic expansion issue. Make sure the
6dedca
buffer used for xmlreader operation is bounded.
6dedca
Introduce a new allocation type for the buffers for this effect.
6dedca
6dedca
Signed-off-by: Daniel Veillard <veillard@redhat.com>
6dedca
---
6dedca
 buf.c                 | 43 ++++++++++++++++++++++++++++++++++++++++++-
6dedca
 include/libxml/tree.h |  3 ++-
6dedca
 xmlreader.c           | 20 +++++++++++++++++++-
6dedca
 3 files changed, 63 insertions(+), 3 deletions(-)
6dedca
6dedca
diff --git a/buf.c b/buf.c
6dedca
index d1756c4..b52e41d 100644
6dedca
--- a/buf.c
6dedca
+++ b/buf.c
6dedca
@@ -27,6 +27,7 @@
6dedca
 #include <libxml/tree.h>
6dedca
 #include <libxml/globals.h>
6dedca
 #include <libxml/tree.h>
6dedca
+#include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
6dedca
 #include "buf.h"
6dedca
 
6dedca
 #define WITH_BUFFER_COMPAT
6dedca
@@ -299,7 +300,8 @@ xmlBufSetAllocationScheme(xmlBufPtr buf,
6dedca
     if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
6dedca
         (scheme == XML_BUFFER_ALLOC_EXACT) ||
6dedca
         (scheme == XML_BUFFER_ALLOC_HYBRID) ||
6dedca
-        (scheme == XML_BUFFER_ALLOC_IMMUTABLE)) {
6dedca
+        (scheme == XML_BUFFER_ALLOC_IMMUTABLE) ||
6dedca
+	(scheme == XML_BUFFER_ALLOC_BOUNDED)) {
6dedca
 	buf->alloc = scheme;
6dedca
         if (buf->buffer)
6dedca
             buf->buffer->alloc = scheme;
6dedca
@@ -458,6 +460,18 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
6dedca
     size = buf->use + len + 100;
6dedca
 #endif
6dedca
 
6dedca
+    if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
6dedca
+        /*
6dedca
+	 * Used to provide parsing limits
6dedca
+	 */
6dedca
+        if ((buf->use + len >= XML_MAX_TEXT_LENGTH) ||
6dedca
+	    (buf->size >= XML_MAX_TEXT_LENGTH)) {
6dedca
+	    xmlBufMemoryError(buf, "buffer error: text too long\n");
6dedca
+	    return(0);
6dedca
+	}
6dedca
+	if (size >= XML_MAX_TEXT_LENGTH)
6dedca
+	    size = XML_MAX_TEXT_LENGTH;
6dedca
+    }
6dedca
     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
6dedca
         size_t start_buf = buf->content - buf->contentIO;
6dedca
 
6dedca
@@ -739,6 +753,15 @@ xmlBufResize(xmlBufPtr buf, size_t size)
6dedca
     CHECK_COMPAT(buf)
6dedca
 
6dedca
     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
6dedca
+    if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
6dedca
+        /*
6dedca
+	 * Used to provide parsing limits
6dedca
+	 */
6dedca
+        if (size >= XML_MAX_TEXT_LENGTH) {
6dedca
+	    xmlBufMemoryError(buf, "buffer error: text too long\n");
6dedca
+	    return(0);
6dedca
+	}
6dedca
+    }
6dedca
 
6dedca
     /* Don't resize if we don't have to */
6dedca
     if (size < buf->size)
6dedca
@@ -867,6 +890,15 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
6dedca
 
6dedca
     needSize = buf->use + len + 2;
6dedca
     if (needSize > buf->size){
6dedca
+	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
6dedca
+	    /*
6dedca
+	     * Used to provide parsing limits
6dedca
+	     */
6dedca
+	    if (needSize >= XML_MAX_TEXT_LENGTH) {
6dedca
+		xmlBufMemoryError(buf, "buffer error: text too long\n");
6dedca
+		return(-1);
6dedca
+	    }
6dedca
+	}
6dedca
         if (!xmlBufResize(buf, needSize)){
6dedca
 	    xmlBufMemoryError(buf, "growing buffer");
6dedca
             return XML_ERR_NO_MEMORY;
6dedca
@@ -938,6 +970,15 @@ xmlBufAddHead(xmlBufPtr buf, const xmlChar *str, int len) {
6dedca
     }
6dedca
     needSize = buf->use + len + 2;
6dedca
     if (needSize > buf->size){
6dedca
+	if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
6dedca
+	    /*
6dedca
+	     * Used to provide parsing limits
6dedca
+	     */
6dedca
+	    if (needSize >= XML_MAX_TEXT_LENGTH) {
6dedca
+		xmlBufMemoryError(buf, "buffer error: text too long\n");
6dedca
+		return(-1);
6dedca
+	    }
6dedca
+	}
6dedca
         if (!xmlBufResize(buf, needSize)){
6dedca
 	    xmlBufMemoryError(buf, "growing buffer");
6dedca
             return XML_ERR_NO_MEMORY;
6dedca
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
6dedca
index 7e06686..d904a44 100644
6dedca
--- a/include/libxml/tree.h
6dedca
+++ b/include/libxml/tree.h
6dedca
@@ -76,7 +76,8 @@ typedef enum {
6dedca
     XML_BUFFER_ALLOC_EXACT,	/* grow only to the minimal size */
6dedca
     XML_BUFFER_ALLOC_IMMUTABLE, /* immutable buffer */
6dedca
     XML_BUFFER_ALLOC_IO,	/* special allocation scheme used for I/O */
6dedca
-    XML_BUFFER_ALLOC_HYBRID	/* exact up to a threshold, and doubleit thereafter */
6dedca
+    XML_BUFFER_ALLOC_HYBRID,	/* exact up to a threshold, and doubleit thereafter */
6dedca
+    XML_BUFFER_ALLOC_BOUNDED	/* limit the upper size of the buffer */
6dedca
 } xmlBufferAllocationScheme;
6dedca
 
6dedca
 /**
6dedca
diff --git a/xmlreader.c b/xmlreader.c
6dedca
index 00083d0..4fabaa9 100644
6dedca
--- a/xmlreader.c
6dedca
+++ b/xmlreader.c
6dedca
@@ -2077,6 +2077,9 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
6dedca
 		"xmlNewTextReader : malloc failed\n");
6dedca
 	return(NULL);
6dedca
     }
6dedca
+    /* no operation on a reader should require a huge buffer */
6dedca
+    xmlBufSetAllocationScheme(ret->buffer,
6dedca
+			      XML_BUFFER_ALLOC_BOUNDED);
6dedca
     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
6dedca
     if (ret->sax == NULL) {
6dedca
 	xmlBufFree(ret->buffer);
6dedca
@@ -3602,6 +3605,7 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) {
6dedca
 	    return(((xmlNsPtr) node)->href);
6dedca
         case XML_ATTRIBUTE_NODE:{
6dedca
 	    xmlAttrPtr attr = (xmlAttrPtr) node;
6dedca
+	    const xmlChar *ret;
6dedca
 
6dedca
 	    if ((attr->children != NULL) &&
6dedca
 	        (attr->children->type == XML_TEXT_NODE) &&
6dedca
@@ -3615,10 +3619,21 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) {
6dedca
                                         "xmlTextReaderSetup : malloc failed\n");
6dedca
                         return (NULL);
6dedca
                     }
6dedca
+		    xmlBufSetAllocationScheme(reader->buffer,
6dedca
+		                              XML_BUFFER_ALLOC_BOUNDED);
6dedca
                 } else
6dedca
                     xmlBufEmpty(reader->buffer);
6dedca
 	        xmlBufGetNodeContent(reader->buffer, node);
6dedca
-		return(xmlBufContent(reader->buffer));
6dedca
+		ret = xmlBufContent(reader->buffer);
6dedca
+		if (ret == NULL) {
6dedca
+		    /* error on the buffer best to reallocate */
6dedca
+		    xmlBufFree(reader->buffer);
6dedca
+		    reader->buffer = xmlBufCreateSize(100);
6dedca
+		    xmlBufSetAllocationScheme(reader->buffer,
6dedca
+		                              XML_BUFFER_ALLOC_BOUNDED);
6dedca
+		    ret = BAD_CAST "";
6dedca
+		}
6dedca
+		return(ret);
6dedca
 	    }
6dedca
 	    break;
6dedca
 	}
6dedca
@@ -5117,6 +5132,9 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
6dedca
                         "xmlTextReaderSetup : malloc failed\n");
6dedca
         return (-1);
6dedca
     }
6dedca
+    /* no operation on a reader should require a huge buffer */
6dedca
+    xmlBufSetAllocationScheme(reader->buffer,
6dedca
+			      XML_BUFFER_ALLOC_BOUNDED);
6dedca
     if (reader->sax == NULL)
6dedca
 	reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
6dedca
     if (reader->sax == NULL) {
6dedca
-- 
6dedca
2.5.0
6dedca