diff options
author | Nick Wellnhofer <wellnhofer@aevum.de> | 2023-02-24 18:00:03 +0100 |
---|---|---|
committer | Nick Wellnhofer <wellnhofer@aevum.de> | 2023-02-26 13:25:01 +0100 |
commit | 0f112d02890c218965235b8d1c42573fcaeec051 (patch) | |
tree | 9298de5005bb7e865c304c15f0ed507cf938c05f /xpath.c | |
parent | a3e11b385c04f2d0dc7d8c51635e5deb5b867261 (diff) | |
download | libxml2-0f112d02890c218965235b8d1c42573fcaeec051.tar.gz |
malloc-fail: Fix use-after-free related to xmlXPathNodeSetFilter
Found with libFuzzer, see #344.
Diffstat (limited to 'xpath.c')
-rw-r--r-- | xpath.c | 21 |
1 files changed, 19 insertions, 2 deletions
@@ -12888,6 +12888,7 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt, { int total = 0; xmlXPathCompExprPtr comp; + xmlXPathObjectPtr obj; xmlNodeSetPtr set; CHECK_ERROR0; @@ -12955,13 +12956,20 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt, } #endif /* LIBXML_XPTR_LOCS_ENABLED */ + /* + * In case of errors, xmlXPathNodeSetFilter can pop additional nodes from + * the stack. We have to temporarily remove the nodeset object from the + * stack to avoid freeing it prematurely. + */ CHECK_TYPE0(XPATH_NODESET); - set = ctxt->value->nodesetval; + obj = valuePop(ctxt); + set = obj->nodesetval; if (set != NULL) { xmlXPathNodeSetFilter(ctxt, set, op->ch2, 1, 1, 1); if (set->nodeNr > 0) *first = set->nodeTab[0]; } + valuePush(ctxt, obj); return (total); } @@ -13259,6 +13267,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) break; case XPATH_OP_PREDICATE: case XPATH_OP_FILTER:{ + xmlXPathObjectPtr obj; xmlNodeSetPtr set; /* @@ -13373,11 +13382,19 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) } #endif /* LIBXML_XPTR_LOCS_ENABLED */ + /* + * In case of errors, xmlXPathNodeSetFilter can pop additional + * nodes from the stack. We have to temporarily remove the + * nodeset object from the stack to avoid freeing it + * prematurely. + */ CHECK_TYPE0(XPATH_NODESET); - set = ctxt->value->nodesetval; + obj = valuePop(ctxt); + set = obj->nodesetval; if (set != NULL) xmlXPathNodeSetFilter(ctxt, set, op->ch2, 1, set->nodeNr, 1); + valuePush(ctxt, obj); break; } case XPATH_OP_SORT: |