--- xpath.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) Index: libxml2-2.12.0/xpath.c =================================================================== --- libxml2-2.12.0.orig/xpath.c +++ libxml2-2.12.0/xpath.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -106,14 +107,32 @@ #define XPATH_MAX_STACK_DEPTH 1000000 /* - * XPATH_MAX_NODESET_LENGTH: + * XPATH_DEFAULT_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 + * arbitrary limit the maximum length of those node set. Default value is + * 10000000, 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. + * + * Adjustable via LIBXML_MAX_NODESET_LENGTH env variable. + * Absolute maximum is INT_MAX. */ -#define XPATH_MAX_NODESET_LENGTH 10000000 +#define XPATH_DEFAULT_MAX_NODESET_LENGTH 10000000 + +int +get_max_nodeset_len() { + const char *max_nodeset_len_str = getenv("LIBXML_MAX_NODESET_LENGTH"); + int max_nodeset_len = XPATH_DEFAULT_MAX_NODESET_LENGTH; + + if (max_nodeset_len_str != NULL) { + max_nodeset_len = strtol(max_nodeset_len_str, NULL, 10); + + if (max_nodeset_len <= 0 || max_nodeset_len > INT_MAX) + max_nodeset_len = XPATH_DEFAULT_MAX_NODESET_LENGTH; + } + + return max_nodeset_len; +} /* * XPATH_MAX_RECRUSION_DEPTH: @@ -3095,7 +3114,7 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, } else if (cur->nodeNr == cur->nodeMax) { xmlNodePtr *temp; - if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) { + if (cur->nodeMax >= get_max_nodeset_len()) { xmlXPathErrMemory(NULL, "growing nodeset hit limit\n"); return(-1); } @@ -3153,7 +3172,7 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xm } else if (cur->nodeNr == cur->nodeMax) { xmlNodePtr *temp; - if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) { + if (cur->nodeMax >= get_max_nodeset_len()) { xmlXPathErrMemory(NULL, "growing nodeset hit limit\n"); return(-1); } @@ -3209,7 +3228,7 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr c } else if (cur->nodeNr == cur->nodeMax) { xmlNodePtr *temp; - if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) { + if (cur->nodeMax >= get_max_nodeset_len()) { xmlXPathErrMemory(NULL, "growing nodeset hit limit\n"); return(-1); } @@ -3302,7 +3321,7 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, } else if (val1->nodeNr == val1->nodeMax) { xmlNodePtr *temp; - if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) { + if (val1->nodeMax >= get_max_nodeset_len()) { xmlXPathErrMemory(NULL, "merging nodeset hit limit\n"); goto error; } @@ -3394,7 +3413,7 @@ xmlXPathNodeSetMergeAndClear(xmlNodeSetP } else if (set1->nodeNr >= set1->nodeMax) { xmlNodePtr *temp; - if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) { + if (set1->nodeMax >= get_max_nodeset_len()) { xmlXPathErrMemory(NULL, "merging nodeset hit limit\n"); goto error; } @@ -3455,7 +3474,7 @@ xmlXPathNodeSetMergeAndClearNoDupls(xmlN } else if (set1->nodeNr >= set1->nodeMax) { xmlNodePtr *temp; - if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) { + if (set1->nodeMax >= get_max_nodeset_len()) { xmlXPathErrMemory(NULL, "merging nodeset hit limit\n"); goto error; }