|
|
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 |
|