mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-03-20 18:50:08 +03:00
Implement some default limits in the XPath module
This adds some internal limitationson XPath expression complexity, and limits at runtime like depth of the stack and maximum size for nodeset. * xpath.c: implement the above as well as the maximum Name lenght
This commit is contained in:
parent
52d8ade7a7
commit
cd852ad154
157
xpath.c
157
xpath.c
@ -91,6 +91,34 @@
|
||||
*/
|
||||
/* #define XP_DEBUG_OBJ_USAGE */
|
||||
|
||||
/*
|
||||
* XPATH_MAX_STEPS:
|
||||
* when compiling an XPath expression we arbitrary limit the maximum
|
||||
* number of step operation in the compiled expression. 1000000 is
|
||||
* an insanely large value which should never be reached under normal
|
||||
* circumstances
|
||||
*/
|
||||
#define XPATH_MAX_STEPS 1000000
|
||||
|
||||
/*
|
||||
* XPATH_MAX_STACK_DEPTH:
|
||||
* when evaluating an XPath expression we arbitrary limit the maximum
|
||||
* number of object allowed to be pushed on the stack. 1000000 is
|
||||
* an insanely large value which should never be reached under normal
|
||||
* circumstances
|
||||
*/
|
||||
#define XPATH_MAX_STACK_DEPTH 1000000
|
||||
|
||||
/*
|
||||
* XPATH_MAX_NODESET_LENGTH:
|
||||
* when evaluating an XPath expression nodesets are created and we
|
||||
* arbitrary limit the maximum length of those node set. 10000000 is
|
||||
* an insanely large value which should never be reached under normal
|
||||
* circumstances, one would first need to construct an in memory tree
|
||||
* with more than 10 millions nodes.
|
||||
*/
|
||||
#define XPATH_MAX_NODESET_LENGTH 10000000
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* There are a few spots where some tests are done which depend upon ascii
|
||||
@ -422,8 +450,7 @@ xmlPointerListAddSize(xmlPointerListPtr list,
|
||||
if (list->items == NULL) {
|
||||
if (initialSize <= 0)
|
||||
initialSize = 1;
|
||||
list->items = (void **) xmlMalloc(
|
||||
initialSize * sizeof(void *));
|
||||
list->items = (void **) xmlMalloc(initialSize * sizeof(void *));
|
||||
if (list->items == NULL) {
|
||||
xmlXPathErrMemory(NULL,
|
||||
"xmlPointerListCreate: allocating item\n");
|
||||
@ -432,12 +459,17 @@ xmlPointerListAddSize(xmlPointerListPtr list,
|
||||
list->number = 0;
|
||||
list->size = initialSize;
|
||||
} else if (list->size <= list->number) {
|
||||
if (list->size > 50000000) {
|
||||
xmlXPathErrMemory(NULL,
|
||||
"xmlPointerListAddSize: re-allocating item\n");
|
||||
return(-1);
|
||||
}
|
||||
list->size *= 2;
|
||||
list->items = (void **) xmlRealloc(list->items,
|
||||
list->size * sizeof(void *));
|
||||
if (list->items == NULL) {
|
||||
xmlXPathErrMemory(NULL,
|
||||
"xmlPointerListCreate: re-allocating item\n");
|
||||
"xmlPointerListAddSize: re-allocating item\n");
|
||||
list->size = 0;
|
||||
return(-1);
|
||||
}
|
||||
@ -725,6 +757,10 @@ xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
|
||||
if (comp->nbStep >= comp->maxStep) {
|
||||
xmlXPathStepOp *real;
|
||||
|
||||
if (comp->maxStep >= XPATH_MAX_STEPS) {
|
||||
xmlXPathErrMemory(NULL, "adding step\n");
|
||||
return(-1);
|
||||
}
|
||||
comp->maxStep *= 2;
|
||||
real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
|
||||
comp->maxStep * sizeof(xmlXPathStepOp));
|
||||
@ -2482,11 +2518,16 @@ valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
|
||||
if (ctxt->valueNr >= ctxt->valueMax) {
|
||||
xmlXPathObjectPtr *tmp;
|
||||
|
||||
if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) {
|
||||
xmlXPathErrMemory(NULL, "XPath stack depth limit reached\n");
|
||||
ctxt->error = XPATH_MEMORY_ERROR;
|
||||
return (0);
|
||||
}
|
||||
tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
|
||||
2 * ctxt->valueMax *
|
||||
sizeof(ctxt->valueTab[0]));
|
||||
if (tmp == NULL) {
|
||||
xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
|
||||
xmlXPathErrMemory(NULL, "pushing value\n");
|
||||
ctxt->error = XPATH_MEMORY_ERROR;
|
||||
return (0);
|
||||
}
|
||||
@ -3568,6 +3609,10 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
|
||||
} else if (cur->nodeNr == cur->nodeMax) {
|
||||
xmlNodePtr *temp;
|
||||
|
||||
if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
|
||||
xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
|
||||
return;
|
||||
}
|
||||
temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
|
||||
sizeof(xmlNodePtr));
|
||||
if (temp == NULL) {
|
||||
@ -3593,11 +3638,6 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
|
||||
|
||||
if ((cur == NULL) || (val == NULL)) return;
|
||||
|
||||
#if 0
|
||||
if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
|
||||
return; /* an XSLT fake node */
|
||||
#endif
|
||||
|
||||
/* @@ with_ns to check whether namespace nodes should be looked at @@ */
|
||||
/*
|
||||
* prevent duplcates
|
||||
@ -3621,6 +3661,10 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
|
||||
} else if (cur->nodeNr == cur->nodeMax) {
|
||||
xmlNodePtr *temp;
|
||||
|
||||
if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
|
||||
xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
|
||||
return;
|
||||
}
|
||||
temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
|
||||
sizeof(xmlNodePtr));
|
||||
if (temp == NULL) {
|
||||
@ -3651,11 +3695,6 @@ void
|
||||
xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
|
||||
if ((cur == NULL) || (val == NULL)) return;
|
||||
|
||||
#if 0
|
||||
if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
|
||||
return; /* an XSLT fake node */
|
||||
#endif
|
||||
|
||||
/* @@ with_ns to check whether namespace nodes should be looked at @@ */
|
||||
/*
|
||||
* grow the nodeTab if needed
|
||||
@ -3673,6 +3712,10 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
|
||||
} else if (cur->nodeNr == cur->nodeMax) {
|
||||
xmlNodePtr *temp;
|
||||
|
||||
if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
|
||||
xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
|
||||
return;
|
||||
}
|
||||
temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
|
||||
sizeof(xmlNodePtr));
|
||||
if (temp == NULL) {
|
||||
@ -3784,6 +3827,10 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
|
||||
} else if (val1->nodeNr == val1->nodeMax) {
|
||||
xmlNodePtr *temp;
|
||||
|
||||
if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
|
||||
xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
|
||||
return(NULL);
|
||||
}
|
||||
temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
|
||||
sizeof(xmlNodePtr));
|
||||
if (temp == NULL) {
|
||||
@ -3805,68 +3852,6 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
|
||||
return(val1);
|
||||
}
|
||||
|
||||
#if 0 /* xmlXPathNodeSetMergeUnique() is currently not used anymore */
|
||||
/**
|
||||
* xmlXPathNodeSetMergeUnique:
|
||||
* @val1: the first NodeSet or NULL
|
||||
* @val2: the second NodeSet
|
||||
*
|
||||
* Merges two nodesets, all nodes from @val2 are added to @val1
|
||||
* if @val1 is NULL, a new set is created and copied from @val2
|
||||
*
|
||||
* Returns @val1 once extended or NULL in case of error.
|
||||
*/
|
||||
static xmlNodeSetPtr
|
||||
xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
|
||||
int i;
|
||||
|
||||
if (val2 == NULL) return(val1);
|
||||
if (val1 == NULL) {
|
||||
val1 = xmlXPathNodeSetCreate(NULL);
|
||||
}
|
||||
if (val1 == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* @@ with_ns to check whether namespace nodes should be looked at @@ */
|
||||
|
||||
for (i = 0;i < val2->nodeNr;i++) {
|
||||
/*
|
||||
* grow the nodeTab if needed
|
||||
*/
|
||||
if (val1->nodeMax == 0) {
|
||||
val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
|
||||
sizeof(xmlNodePtr));
|
||||
if (val1->nodeTab == NULL) {
|
||||
xmlXPathErrMemory(NULL, "merging nodeset\n");
|
||||
return(NULL);
|
||||
}
|
||||
memset(val1->nodeTab, 0 ,
|
||||
XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
|
||||
val1->nodeMax = XML_NODESET_DEFAULT;
|
||||
} else if (val1->nodeNr == val1->nodeMax) {
|
||||
xmlNodePtr *temp;
|
||||
|
||||
val1->nodeMax *= 2;
|
||||
temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
|
||||
sizeof(xmlNodePtr));
|
||||
if (temp == NULL) {
|
||||
xmlXPathErrMemory(NULL, "merging nodeset\n");
|
||||
return(NULL);
|
||||
}
|
||||
val1->nodeTab = temp;
|
||||
}
|
||||
if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
|
||||
xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
|
||||
|
||||
val1->nodeTab[val1->nodeNr++] =
|
||||
xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
|
||||
} else
|
||||
val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
|
||||
}
|
||||
|
||||
return(val1);
|
||||
}
|
||||
#endif /* xmlXPathNodeSetMergeUnique() is currently not used anymore */
|
||||
|
||||
/**
|
||||
* xmlXPathNodeSetMergeAndClear:
|
||||
@ -3953,6 +3938,10 @@ xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
|
||||
} else if (set1->nodeNr >= set1->nodeMax) {
|
||||
xmlNodePtr *temp;
|
||||
|
||||
if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
|
||||
xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
|
||||
return(NULL);
|
||||
}
|
||||
temp = (xmlNodePtr *) xmlRealloc(
|
||||
set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
|
||||
if (temp == NULL) {
|
||||
@ -4037,6 +4026,10 @@ xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
|
||||
} else if (set1->nodeNr >= set1->nodeMax) {
|
||||
xmlNodePtr *temp;
|
||||
|
||||
if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
|
||||
xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
|
||||
return(NULL);
|
||||
}
|
||||
temp = (xmlNodePtr *) xmlRealloc(
|
||||
set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
|
||||
if (temp == NULL) {
|
||||
@ -9868,7 +9861,7 @@ xmlChar *
|
||||
xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
|
||||
const xmlChar *in;
|
||||
xmlChar *ret;
|
||||
int count = 0;
|
||||
size_t count = 0;
|
||||
|
||||
if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
|
||||
/*
|
||||
@ -9887,6 +9880,10 @@ xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
|
||||
in++;
|
||||
if ((*in > 0) && (*in < 0x80)) {
|
||||
count = in - ctxt->cur;
|
||||
if (count > XML_MAX_NAME_LENGTH) {
|
||||
ctxt->cur = in;
|
||||
XP_ERRORNULL(XPATH_EXPR_ERROR);
|
||||
}
|
||||
ret = xmlStrndup(ctxt->cur, count);
|
||||
ctxt->cur = in;
|
||||
return(ret);
|
||||
@ -9930,6 +9927,9 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
|
||||
xmlChar *buffer;
|
||||
int max = len * 2;
|
||||
|
||||
if (len > XML_MAX_NAME_LENGTH) {
|
||||
XP_ERRORNULL(XPATH_EXPR_ERROR);
|
||||
}
|
||||
buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
|
||||
if (buffer == NULL) {
|
||||
XP_ERRORNULL(XPATH_MEMORY_ERROR);
|
||||
@ -9941,6 +9941,9 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
|
||||
(IS_COMBINING(c)) ||
|
||||
(IS_EXTENDER(c))) {
|
||||
if (len + 10 > max) {
|
||||
if (max > XML_MAX_NAME_LENGTH) {
|
||||
XP_ERRORNULL(XPATH_EXPR_ERROR);
|
||||
}
|
||||
max *= 2;
|
||||
buffer = (xmlChar *) xmlRealloc(buffer,
|
||||
max * sizeof(xmlChar));
|
||||
|
Loading…
x
Reference in New Issue
Block a user