blob: bb55eed171fde07a44e6dd51ac63a2db49e265b8 [file] [log] [blame]
libxml2-2.9.4: Fix CVE-2016-4658
[No upstream tracking] -- https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2016-4658
xpointer: Disallow namespace nodes in XPointer points and ranges
Namespace nodes must be copied to avoid use-after-free errors.
But they don't necessarily have a physical representation in a
document, so simply disallow them in XPointer ranges.
Upstream-Status: Backport
- [https://git.gnome.org/browse/libxml2/commit/?id=c1d1f7121194036608bf555f08d3062a36fd344b]
- [https://git.gnome.org/browse/libxml2/commit/?id=3f8a91036d338e51c059d54397a42d645f019c65]
CVE: CVE-2016-4658
Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
Signed-off-by: Pascal Bach <pascal.bach@siemens.com>
diff --git a/xpointer.c b/xpointer.c
index 676c510..911680d 100644
--- a/xpointer.c
+++ b/xpointer.c
@@ -320,6 +320,45 @@ xmlXPtrRangesEqual(xmlXPathObjectPtr range1, xmlXPathObjectPtr range2) {
}
/**
+ * xmlXPtrNewRangeInternal:
+ * @start: the starting node
+ * @startindex: the start index
+ * @end: the ending point
+ * @endindex: the ending index
+ *
+ * Internal function to create a new xmlXPathObjectPtr of type range
+ *
+ * Returns the newly created object.
+ */
+static xmlXPathObjectPtr
+xmlXPtrNewRangeInternal(xmlNodePtr start, int startindex,
+ xmlNodePtr end, int endindex) {
+ xmlXPathObjectPtr ret;
+
+ /*
+ * Namespace nodes must be copied (see xmlXPathNodeSetDupNs).
+ * Disallow them for now.
+ */
+ if ((start != NULL) && (start->type == XML_NAMESPACE_DECL))
+ return(NULL);
+ if ((end != NULL) && (end->type == XML_NAMESPACE_DECL))
+ return(NULL);
+
+ ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
+ if (ret == NULL) {
+ xmlXPtrErrMemory("allocating range");
+ return(NULL);
+ }
+ memset(ret, 0, sizeof(xmlXPathObject));
+ ret->type = XPATH_RANGE;
+ ret->user = start;
+ ret->index = startindex;
+ ret->user2 = end;
+ ret->index2 = endindex;
+ return(ret);
+}
+
+/**
* xmlXPtrNewRange:
* @start: the starting node
* @startindex: the start index
@@ -344,17 +383,7 @@ xmlXPtrNewRange(xmlNodePtr start, int startindex,
if (endindex < 0)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start;
- ret->index = startindex;
- ret->user2 = end;
- ret->index2 = endindex;
+ ret = xmlXPtrNewRangeInternal(start, startindex, end, endindex);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -381,17 +410,8 @@ xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) {
if (end->type != XPATH_POINT)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start->user;
- ret->index = start->index;
- ret->user2 = end->user;
- ret->index2 = end->index;
+ ret = xmlXPtrNewRangeInternal(start->user, start->index, end->user,
+ end->index);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -416,17 +436,7 @@ xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) {
if (start->type != XPATH_POINT)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start->user;
- ret->index = start->index;
- ret->user2 = end;
- ret->index2 = -1;
+ ret = xmlXPtrNewRangeInternal(start->user, start->index, end, -1);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -453,17 +463,7 @@ xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) {
if (end->type != XPATH_POINT)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start;
- ret->index = -1;
- ret->user2 = end->user;
- ret->index2 = end->index;
+ ret = xmlXPtrNewRangeInternal(start, -1, end->user, end->index);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -486,17 +486,7 @@ xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) {
if (end == NULL)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start;
- ret->index = -1;
- ret->user2 = end;
- ret->index2 = -1;
+ ret = xmlXPtrNewRangeInternal(start, -1, end, -1);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -516,17 +506,7 @@ xmlXPtrNewCollapsedRange(xmlNodePtr start) {
if (start == NULL)
return(NULL);
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start;
- ret->index = -1;
- ret->user2 = NULL;
- ret->index2 = -1;
+ ret = xmlXPtrNewRangeInternal(start, -1, NULL, -1);
return(ret);
}
@@ -541,6 +521,8 @@ xmlXPtrNewCollapsedRange(xmlNodePtr start) {
*/
xmlXPathObjectPtr
xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
+ xmlNodePtr endNode;
+ int endIndex;
xmlXPathObjectPtr ret;
if (start == NULL)
@@ -549,7 +531,12 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
return(NULL);
switch (end->type) {
case XPATH_POINT:
+ endNode = end->user;
+ endIndex = end->index;
+ break;
case XPATH_RANGE:
+ endNode = end->user2;
+ endIndex = end->index2;
break;
case XPATH_NODESET:
/*
@@ -557,39 +544,15 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
*/
if (end->nodesetval->nodeNr <= 0)
return(NULL);
+ endNode = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
+ endIndex = -1;
break;
default:
/* TODO */
return(NULL);
}
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- xmlXPtrErrMemory("allocating range");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_RANGE;
- ret->user = start;
- ret->index = -1;
- switch (end->type) {
- case XPATH_POINT:
- ret->user2 = end->user;
- ret->index2 = end->index;
- break;
- case XPATH_RANGE:
- ret->user2 = end->user2;
- ret->index2 = end->index2;
- break;
- case XPATH_NODESET: {
- ret->user2 = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
- ret->index2 = -1;
- break;
- }
- default:
- STRANGE
- return(NULL);
- }
+ ret = xmlXPtrNewRangeInternal(start, -1, endNode, endIndex);
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
@@ -1835,8 +1798,8 @@ xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
case XPATH_RANGE: {
xmlNodePtr node = tmp->user;
if (node != NULL) {
- if (node->type == XML_ATTRIBUTE_NODE) {
- /* TODO: Namespace Nodes ??? */
+ if ((node->type == XML_ATTRIBUTE_NODE) ||
+ (node->type == XML_NAMESPACE_DECL)) {
xmlXPathFreeObject(obj);
xmlXPtrFreeLocationSet(newset);
XP_ERROR(XPTR_SYNTAX_ERROR);
@@ -1931,8 +1894,8 @@ xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
case XPATH_RANGE: {
xmlNodePtr node = tmp->user2;
if (node != NULL) {
- if (node->type == XML_ATTRIBUTE_NODE) {
- /* TODO: Namespace Nodes ??? */
+ if ((node->type == XML_ATTRIBUTE_NODE) ||
+ (node->type == XML_NAMESPACE_DECL)) {
xmlXPathFreeObject(obj);
xmlXPtrFreeLocationSet(newset);
XP_ERROR(XPTR_SYNTAX_ERROR);