123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- From c1d1f7121194036608bf555f08d3062a36fd344b Mon Sep 17 00:00:00 2001
- From: Nick Wellnhofer <wellnhofer@aevum.de>
- Date: Tue, 28 Jun 2016 18:34:52 +0200
- Subject: [PATCH] Disallow namespace nodes in XPointer 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.
- Found with afl-fuzz.
- Fixes CVE-2016-4658.
- ---
- xpointer.c | 149 +++++++++++++++++++++++--------------------------------------
- 1 file changed, 56 insertions(+), 93 deletions(-)
- diff --git a/xpointer.c b/xpointer.c
- index a7b03fb..694d120 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);
- }
- --
- 2.10.1
|