Blame SOURCES/libxml2-More-format-string-warnings-with-possible-format-string-vulnerability.patch

1c8959
From 6a2a4e753bbba26b2de3d32f11c28691bec967dc Mon Sep 17 00:00:00 2001
1c8959
From: David Kilzer <ddkilzer@apple.com>
1c8959
Date: Mon, 23 May 2016 14:58:41 +0800
1c8959
Subject: [PATCH] More format string warnings with possible format string
1c8959
 vulnerability
1c8959
To: libvir-list@redhat.com
1c8959
1c8959
For https://bugzilla.gnome.org/show_bug.cgi?id=761029
1c8959
1c8959
adds a new xmlEscapeFormatString() function to escape composed format
1c8959
strings
1c8959
1c8959
Signed-off-by: Daniel Veillard <veillard@redhat.com>
1c8959
---
1c8959
 libxml.h     |  3 +++
1c8959
 relaxng.c    |  3 ++-
1c8959
 xmlschemas.c | 39 ++++++++++++++++++++++++++-------------
1c8959
 xmlstring.c  | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1c8959
 4 files changed, 86 insertions(+), 14 deletions(-)
1c8959
1c8959
diff --git a/libxml.h b/libxml.h
1c8959
index 4558b70..88e515f 100644
1c8959
--- a/libxml.h
1c8959
+++ b/libxml.h
1c8959
@@ -9,6 +9,8 @@
1c8959
 #ifndef __XML_LIBXML_H__
1c8959
 #define __XML_LIBXML_H__
1c8959
 
1c8959
+#include <libxml/xmlstring.h>
1c8959
+
1c8959
 #ifndef NO_LARGEFILE_SOURCE
1c8959
 #ifndef _LARGEFILE_SOURCE
1c8959
 #define _LARGEFILE_SOURCE
1c8959
@@ -93,6 +95,7 @@ int __xmlInitializeDict(void);
1c8959
 int __xmlRandom(void);
1c8959
 #endif
1c8959
 
1c8959
+XMLPUBFUN xmlChar * XMLCALL xmlEscapeFormatString(xmlChar **msg);
1c8959
 int xmlNop(void);
1c8959
 
1c8959
 #ifdef IN_LIBXML
1c8959
diff --git a/relaxng.c b/relaxng.c
1c8959
index b531081..99e9901 100644
1c8959
--- a/relaxng.c
1c8959
+++ b/relaxng.c
1c8959
@@ -2215,7 +2215,8 @@ xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
1c8959
         snprintf(msg, 1000, "Unknown error code %d\n", err);
1c8959
     }
1c8959
     msg[1000 - 1] = 0;
1c8959
-    return (xmlStrdup((xmlChar *) msg));
1c8959
+    xmlChar *result = xmlCharStrdup(msg);
1c8959
+    return (xmlEscapeFormatString(&result));
1c8959
 }
1c8959
 
1c8959
 /**
1c8959
diff --git a/xmlschemas.c b/xmlschemas.c
1c8959
index 398cdd8..1bcb0f0 100644
1c8959
--- a/xmlschemas.c
1c8959
+++ b/xmlschemas.c
1c8959
@@ -1769,7 +1769,7 @@ xmlSchemaFormatItemForReport(xmlChar **buf,
1c8959
     }
1c8959
     FREE_AND_NULL(str)
1c8959
 
1c8959
-    return (*buf);
1c8959
+    return (xmlEscapeFormatString(buf));
1c8959
 }
1c8959
 
1c8959
 /**
1c8959
@@ -2247,6 +2247,13 @@ xmlSchemaFormatNodeForError(xmlChar ** msg,
1c8959
 	TODO
1c8959
 	return (NULL);
1c8959
     }
1c8959
+
1c8959
+    /*
1c8959
+     * xmlSchemaFormatItemForReport() also returns an escaped format
1c8959
+     * string, so do this before calling it below (in the future).
1c8959
+     */
1c8959
+    xmlEscapeFormatString(msg);
1c8959
+
1c8959
     /*
1c8959
     * VAL TODO: The output of the given schema component is currently
1c8959
     * disabled.
1c8959
@@ -2474,11 +2481,13 @@ xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1c8959
 	msg = xmlStrcat(msg, BAD_CAST " '");
1c8959
 	if (type->builtInType != 0) {
1c8959
 	    msg = xmlStrcat(msg, BAD_CAST "xs:");
1c8959
-	    msg = xmlStrcat(msg, type->name);
1c8959
-	} else
1c8959
-	    msg = xmlStrcat(msg,
1c8959
-		xmlSchemaFormatQName(&str,
1c8959
-		    type->targetNamespace, type->name));
1c8959
+	    str = xmlStrdup(type->name);
1c8959
+	} else {
1c8959
+	    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
1c8959
+	    if (!str)
1c8959
+		str = xmlStrdup(qName);
1c8959
+	}
1c8959
+	msg = xmlStrcat(msg, xmlEscapeFormatString(&str);;
1c8959
 	msg = xmlStrcat(msg, BAD_CAST "'");
1c8959
 	FREE_AND_NULL(str);
1c8959
     }
1c8959
@@ -2615,7 +2624,7 @@ xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1c8959
 		str = xmlStrcat(str, BAD_CAST ", ");
1c8959
 	}
1c8959
 	str = xmlStrcat(str, BAD_CAST " ).\n");
1c8959
-	msg = xmlStrcat(msg, BAD_CAST str);
1c8959
+	msg = xmlStrcat(msg, xmlEscapeFormatString(&str);;
1c8959
 	FREE_AND_NULL(str)
1c8959
     } else
1c8959
       msg = xmlStrcat(msg, BAD_CAST "\n");
1c8959
@@ -3139,11 +3148,13 @@ xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1c8959
 		msg = xmlStrcat(msg, BAD_CAST " '");
1c8959
 		if (type->builtInType != 0) {
1c8959
 		    msg = xmlStrcat(msg, BAD_CAST "xs:");
1c8959
-		    msg = xmlStrcat(msg, type->name);
1c8959
-		} else
1c8959
-		    msg = xmlStrcat(msg,
1c8959
-			xmlSchemaFormatQName(&str,
1c8959
-			    type->targetNamespace, type->name));
1c8959
+		    str = xmlStrdup(type->name);
1c8959
+		} else {
1c8959
+		    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
1c8959
+		    if (!str)
1c8959
+			str = xmlStrdup(qName);
1c8959
+		}
1c8959
+		msg = xmlStrcat(msg, xmlEscapeFormatString(&str);;
1c8959
 		msg = xmlStrcat(msg, BAD_CAST "'.");
1c8959
 		FREE_AND_NULL(str);
1c8959
 	    }
1c8959
@@ -3156,7 +3167,9 @@ xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1c8959
 	}
1c8959
 	if (expected) {
1c8959
 	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
1c8959
-	    msg = xmlStrcat(msg, BAD_CAST expected);
1c8959
+	    xmlChar *expectedEscaped = xmlCharStrdup(expected);
1c8959
+	    msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
1c8959
+	    FREE_AND_NULL(expectedEscaped);
1c8959
 	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
1c8959
 	} else
1c8959
 	    msg = xmlStrcat(msg, BAD_CAST "\n");
1c8959
diff --git a/xmlstring.c b/xmlstring.c
1c8959
index c66eef3..9164d2e 100644
1c8959
--- a/xmlstring.c
1c8959
+++ b/xmlstring.c
1c8959
@@ -987,5 +987,60 @@ xmlUTF8Strsub(const xmlChar *utf, int start, int len) {
1c8959
     return(xmlUTF8Strndup(utf, len));
1c8959
 }
1c8959
 
1c8959
+/**
1c8959
+ * xmlEscapeFormatString:
1c8959
+ * @msg:  a pointer to the string in which to escape '%' characters.
1c8959
+ * Must be a heap-allocated buffer created by libxml2 that may be
1c8959
+ * returned, or that may be freed and replaced.
1c8959
+ *
1c8959
+ * Replaces the string pointed to by 'msg' with an escaped string.
1c8959
+ * Returns the same string with all '%' characters escaped.
1c8959
+ */
1c8959
+xmlChar *
1c8959
+xmlEscapeFormatString(xmlChar **msg)
1c8959
+{
1c8959
+    xmlChar *msgPtr = NULL;
1c8959
+    xmlChar *result = NULL;
1c8959
+    xmlChar *resultPtr = NULL;
1c8959
+    size_t count = 0;
1c8959
+    size_t msgLen = 0;
1c8959
+    size_t resultLen = 0;
1c8959
+
1c8959
+    if (!msg || !*msg)
1c8959
+        return(NULL);
1c8959
+
1c8959
+    for (msgPtr = *msg; *msgPtr != '\0'; ++msgPtr) {
1c8959
+        ++msgLen;
1c8959
+        if (*msgPtr == '%')
1c8959
+            ++count;
1c8959
+    }
1c8959
+
1c8959
+    if (count == 0)
1c8959
+        return(*msg);
1c8959
+
1c8959
+    resultLen = msgLen + count + 1;
1c8959
+    result = (xmlChar *) xmlMallocAtomic(resultLen * sizeof(xmlChar));
1c8959
+    if (result == NULL) {
1c8959
+        /* Clear *msg to prevent format string vulnerabilities in
1c8959
+           out-of-memory situations. */
1c8959
+        xmlFree(*msg);
1c8959
+        *msg = NULL;
1c8959
+        xmlErrMemory(NULL, NULL);
1c8959
+        return(NULL);
1c8959
+    }
1c8959
+
1c8959
+    for (msgPtr = *msg, resultPtr = result; *msgPtr != '\0'; ++msgPtr, ++resultPtr) {
1c8959
+        *resultPtr = *msgPtr;
1c8959
+        if (*msgPtr == '%')
1c8959
+            *(++resultPtr) = '%';
1c8959
+    }
1c8959
+    result[resultLen - 1] = '\0';
1c8959
+
1c8959
+    xmlFree(*msg);
1c8959
+    *msg = result;
1c8959
+
1c8959
+    return *msg;
1c8959
+}
1c8959
+
1c8959
 #define bottom_xmlstring
1c8959
 #include "elfgcchack.h"
1c8959
-- 
1c8959
2.5.5
1c8959