| 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. |
| |
| Signed-off-by: Baruch Siach <baruch@tkos.co.il> |
| --- |
| Patch status: upstream commit c1d1f712119403 |
| |
| xpointer.c | 149 +++++++++++++++++++++++-------------------------------------- |
| 1 file changed, 56 insertions(+), 93 deletions(-) |
| |
| diff --git a/xpointer.c b/xpointer.c |
| index a7b03fbdae16..694d120e2e0b 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.2 |
| |