You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
6.0 KiB
208 lines
6.0 KiB
From 6a2a4e753bbba26b2de3d32f11c28691bec967dc Mon Sep 17 00:00:00 2001 |
|
From: David Kilzer <ddkilzer@apple.com> |
|
Date: Mon, 23 May 2016 14:58:41 +0800 |
|
Subject: [PATCH] More format string warnings with possible format string |
|
vulnerability |
|
To: libvir-list@redhat.com |
|
|
|
For https://bugzilla.gnome.org/show_bug.cgi?id=761029 |
|
|
|
adds a new xmlEscapeFormatString() function to escape composed format |
|
strings |
|
|
|
Signed-off-by: Daniel Veillard <veillard@redhat.com> |
|
--- |
|
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 b531081..99e9901 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 398cdd8..1bcb0f0 100644 |
|
--- a/xmlschemas.c |
|
+++ b/xmlschemas.c |
|
@@ -1769,7 +1769,7 @@ xmlSchemaFormatItemForReport(xmlChar **buf, |
|
} |
|
FREE_AND_NULL(str) |
|
|
|
- return (*buf); |
|
+ return (xmlEscapeFormatString(buf)); |
|
} |
|
|
|
/** |
|
@@ -2247,6 +2247,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. |
|
@@ -2474,11 +2481,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); |
|
} |
|
@@ -2615,7 +2624,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"); |
|
@@ -3139,11 +3148,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); |
|
} |
|
@@ -3156,7 +3167,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 c66eef3..9164d2e 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" |
|
-- |
|
2.5.5 |
|
|
|
|