[libxml2] More format string warnings with possible format string vulnerability



commit 502f6a6d08b08c04b3ddfb1cd21b2f699c1b7f5b
Author: David Kilzer <ddkilzer apple com>
Date:   Mon May 23 14:58:41 2016 +0800

    More format string warnings with possible format string vulnerability
    
    For https://bugzilla.gnome.org/show_bug.cgi?id=761029
    
    adds a new xmlEscapeFormatString() function to escape composed format
    strings

 libxml.h     |    3 +++
 relaxng.c    |    3 ++-
 xmlschemas.c |   39 ++++++++++++++++++++++++++-------------
 xmlstring.c  |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 86 insertions(+), 14 deletions(-)
---
diff --git a/libxml.h b/libxml.h
index 4558b70..88e515f 100644
--- a/libxml.h
+++ b/libxml.h
@@ -9,6 +9,8 @@
 #ifndef __XML_LIBXML_H__
 #define __XML_LIBXML_H__
 
+#include <libxml/xmlstring.h>
+
 #ifndef NO_LARGEFILE_SOURCE
 #ifndef _LARGEFILE_SOURCE
 #define _LARGEFILE_SOURCE
@@ -93,6 +95,7 @@ int __xmlInitializeDict(void);
 int __xmlRandom(void);
 #endif
 
+XMLPUBFUN xmlChar * XMLCALL xmlEscapeFormatString(xmlChar **msg);
 int xmlNop(void);
 
 #ifdef IN_LIBXML
diff --git a/relaxng.c b/relaxng.c
index 345f354..56a3344 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -2215,7 +2215,8 @@ xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
         snprintf(msg, 1000, "Unknown error code %d\n", err);
     }
     msg[1000 - 1] = 0;
-    return (xmlStrdup((xmlChar *) msg));
+    xmlChar *result = xmlCharStrdup(msg);
+    return (xmlEscapeFormatString(&result));
 }
 
 /**
diff --git a/xmlschemas.c b/xmlschemas.c
index 76f2119..e1b3a4f 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -1769,7 +1769,7 @@ xmlSchemaFormatItemForReport(xmlChar **buf,
     }
     FREE_AND_NULL(str)
 
-    return (*buf);
+    return (xmlEscapeFormatString(buf));
 }
 
 /**
@@ -2249,6 +2249,13 @@ xmlSchemaFormatNodeForError(xmlChar ** msg,
        TODO
        return (NULL);
     }
+
+    /*
+     * xmlSchemaFormatItemForReport() also returns an escaped format
+     * string, so do this before calling it below (in the future).
+     */
+    xmlEscapeFormatString(msg);
+
     /*
     * VAL TODO: The output of the given schema component is currently
     * disabled.
@@ -2476,11 +2483,13 @@ xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
        msg = xmlStrcat(msg, BAD_CAST " '");
        if (type->builtInType != 0) {
            msg = xmlStrcat(msg, BAD_CAST "xs:");
-           msg = xmlStrcat(msg, type->name);
-       } else
-           msg = xmlStrcat(msg,
-               xmlSchemaFormatQName(&str,
-                   type->targetNamespace, type->name));
+           str = xmlStrdup(type->name);
+       } else {
+           const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
+           if (!str)
+               str = xmlStrdup(qName);
+       }
+       msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
        msg = xmlStrcat(msg, BAD_CAST "'");
        FREE_AND_NULL(str);
     }
@@ -2617,7 +2626,7 @@ xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
                str = xmlStrcat(str, BAD_CAST ", ");
        }
        str = xmlStrcat(str, BAD_CAST " ).\n");
-       msg = xmlStrcat(msg, BAD_CAST str);
+       msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
        FREE_AND_NULL(str)
     } else
       msg = xmlStrcat(msg, BAD_CAST "\n");
@@ -3141,11 +3150,13 @@ xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
                msg = xmlStrcat(msg, BAD_CAST " '");
                if (type->builtInType != 0) {
                    msg = xmlStrcat(msg, BAD_CAST "xs:");
-                   msg = xmlStrcat(msg, type->name);
-               } else
-                   msg = xmlStrcat(msg,
-                       xmlSchemaFormatQName(&str,
-                           type->targetNamespace, type->name));
+                   str = xmlStrdup(type->name);
+               } else {
+                   const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
+                   if (!str)
+                       str = xmlStrdup(qName);
+               }
+               msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
                msg = xmlStrcat(msg, BAD_CAST "'.");
                FREE_AND_NULL(str);
            }
@@ -3158,7 +3169,9 @@ xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
        }
        if (expected) {
            msg = xmlStrcat(msg, BAD_CAST " Expected is '");
-           msg = xmlStrcat(msg, BAD_CAST expected);
+           xmlChar *expectedEscaped = xmlCharStrdup(expected);
+           msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
+           FREE_AND_NULL(expectedEscaped);
            msg = xmlStrcat(msg, BAD_CAST "'.\n");
        } else
            msg = xmlStrcat(msg, BAD_CAST "\n");
diff --git a/xmlstring.c b/xmlstring.c
index 42e380f..cc85777 100644
--- a/xmlstring.c
+++ b/xmlstring.c
@@ -987,5 +987,60 @@ xmlUTF8Strsub(const xmlChar *utf, int start, int len) {
     return(xmlUTF8Strndup(utf, len));
 }
 
+/**
+ * xmlEscapeFormatString:
+ * @msg:  a pointer to the string in which to escape '%' characters.
+ * Must be a heap-allocated buffer created by libxml2 that may be
+ * returned, or that may be freed and replaced.
+ *
+ * Replaces the string pointed to by 'msg' with an escaped string.
+ * Returns the same string with all '%' characters escaped.
+ */
+xmlChar *
+xmlEscapeFormatString(xmlChar **msg)
+{
+    xmlChar *msgPtr = NULL;
+    xmlChar *result = NULL;
+    xmlChar *resultPtr = NULL;
+    size_t count = 0;
+    size_t msgLen = 0;
+    size_t resultLen = 0;
+
+    if (!msg || !*msg)
+        return(NULL);
+
+    for (msgPtr = *msg; *msgPtr != '\0'; ++msgPtr) {
+        ++msgLen;
+        if (*msgPtr == '%')
+            ++count;
+    }
+
+    if (count == 0)
+        return(*msg);
+
+    resultLen = msgLen + count + 1;
+    result = (xmlChar *) xmlMallocAtomic(resultLen * sizeof(xmlChar));
+    if (result == NULL) {
+        /* Clear *msg to prevent format string vulnerabilities in
+           out-of-memory situations. */
+        xmlFree(*msg);
+        *msg = NULL;
+        xmlErrMemory(NULL, NULL);
+        return(NULL);
+    }
+
+    for (msgPtr = *msg, resultPtr = result; *msgPtr != '\0'; ++msgPtr, ++resultPtr) {
+        *resultPtr = *msgPtr;
+        if (*msgPtr == '%')
+            *(++resultPtr) = '%';
+    }
+    result[resultLen - 1] = '\0';
+
+    xmlFree(*msg);
+    *msg = result;
+
+    return *msg;
+}
+
 #define bottom_xmlstring
 #include "elfgcchack.h"


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]