• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1From 0f112d02890c218965235b8d1c42573fcaeec051 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Fri, 24 Feb 2023 18:00:03 +0100
4Subject: [PATCH] malloc-fail: Fix use-after-free related to
5 xmlXPathNodeSetFilter
6
7Found with libFuzzer, see #344.
8
9Reference:https://github.com/GNOME/libxml2/commit/0f112d02890c218965235b8d1c42573fcaeec051
10Conflict:xpath.c
11---
12 xpath.c | 21 +++++++++++++++++++--
13 1 file changed, 19 insertions(+), 2 deletions(-)
14
15diff --git a/xpath.c b/xpath.c
16index 7f2c92a..d63bdd7 100644
17--- a/xpath.c
18+++ b/xpath.c
19@@ -12876,6 +12876,7 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
20 {
21     int total = 0;
22     xmlXPathCompExprPtr comp;
23+    xmlXPathObjectPtr obj;
24     xmlNodeSetPtr set;
25
26     CHECK_ERROR0;
27@@ -12943,13 +12944,20 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
28     }
29 #endif /* LIBXML_XPTR_ENABLED */
30
31+    /*
32+     * In case of errors, xmlXPathNodeSetFilter can pop additional nodes from
33+     * the stack. We have to temporarily remove the nodeset object from the
34+     * stack to avoid freeing it prematurely.
35+     */
36     CHECK_TYPE0(XPATH_NODESET);
37-    set = ctxt->value->nodesetval;
38+    obj = valuePop(ctxt);
39+    set = obj->nodesetval;
40     if (set != NULL) {
41         xmlXPathNodeSetFilter(ctxt, set, op->ch2, 1, 1, 1);
42         if (set->nodeNr > 0)
43             *first = set->nodeTab[0];
44     }
45+    valuePush(ctxt, obj);
46
47     return (total);
48 }
49@@ -13247,6 +13255,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
50             break;
51         case XPATH_OP_PREDICATE:
52         case XPATH_OP_FILTER:{
53+                xmlXPathObjectPtr obj;
54                 xmlNodeSetPtr set;
55
56                 /*
57@@ -13361,11 +13370,19 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
58                 }
59 #endif /* LIBXML_XPTR_ENABLED */
60
61+                /*
62+                 * In case of errors, xmlXPathNodeSetFilter can pop additional
63+                 * nodes from the stack. We have to temporarily remove the
64+                 * nodeset object from the stack to avoid freeing it
65+                 * prematurely.
66+                 */
67                 CHECK_TYPE0(XPATH_NODESET);
68-                set = ctxt->value->nodesetval;
69+                obj = valuePop(ctxt);
70+                set = obj->nodesetval;
71                 if (set != NULL)
72                     xmlXPathNodeSetFilter(ctxt, set, op->ch2,
73                                           1, set->nodeNr, 1);
74+                valuePush(ctxt, obj);
75                 break;
76             }
77         case XPATH_OP_SORT:
78--
792.27.0
80
81