xzyang / rpms / libxml2

Forked from rpms/libxml2 3 years ago
Clone

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

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