1From 2fbf7876510dd9c5996151e2569078146e869697 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Wed, 2 Nov 2022 16:22:54 +0100
4Subject: [PATCH 12/28] malloc-fail: Fix memory leak in xmlStringGetNodeList
5
6Also make sure to return NULL on error instead of a partial node list.
7
8Found with libFuzzer, see #344.
9
10Reference: https://github.com/GNOME/libxml2/commit/b45927095e0c857b68a96466e3075d60a6a5dd9e
11Conflict: NA
12---
13 tree.c | 36 ++++++++++++++++++------------------
14 1 file changed, 18 insertions(+), 18 deletions(-)
15
16diff --git a/tree.c b/tree.c
17index bb85220..ac156e1 100644
18--- a/tree.c
19+++ b/tree.c
20@@ -1496,9 +1496,9 @@ out:
21  */
22 xmlNodePtr
23 xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
24-    xmlNodePtr ret = NULL, last = NULL;
25+    xmlNodePtr ret = NULL, head = NULL, last = NULL;
26     xmlNodePtr node;
27-    xmlChar *val;
28+    xmlChar *val = NULL;
29     const xmlChar *cur = value;
30     const xmlChar *q;
31     xmlEntityPtr ent;
32@@ -1596,14 +1596,12 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
33 			 */
34 			if (!xmlBufIsEmpty(buf)) {
35 			    node = xmlNewDocText(doc, NULL);
36-			    if (node == NULL) {
37-				if (val != NULL) xmlFree(val);
38-				goto out;
39-			    }
40+                            if (node == NULL)
41+                                goto out;
42 			    node->content = xmlBufDetach(buf);
43 
44 			    if (last == NULL) {
45-				last = ret = node;
46+				last = head = node;
47 			    } else {
48 				last = xmlAddNextSibling(last, node);
49 			    }
50@@ -1613,11 +1611,9 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
51 			 * Create a new REFERENCE_REF node
52 			 */
53 			node = xmlNewReference(doc, val);
54-			if (node == NULL) {
55-			    if (val != NULL) xmlFree(val);
56+			if (node == NULL)
57 			    goto out;
58-			}
59-			else if ((ent != NULL) && (ent->children == NULL)) {
60+			if ((ent != NULL) && (ent->children == NULL)) {
61 			    xmlNodePtr temp;
62 
63                             /* Set to non-NULL value to avoid recursion. */
64@@ -1633,12 +1629,13 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
65 			    }
66 			}
67 			if (last == NULL) {
68-			    last = ret = node;
69+			    last = head = node;
70 			} else {
71 			    last = xmlAddNextSibling(last, node);
72 			}
73 		    }
74 		    xmlFree(val);
75+                    val = NULL;
76 		}
77 		cur++;
78 		q = cur;
79@@ -1657,7 +1654,7 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
80 	} else
81 	    cur++;
82     }
83-    if ((cur != q) || (ret == NULL)) {
84+    if ((cur != q) || (head == NULL)) {
85         /*
86 	 * Handle the last piece of text.
87 	 */
88@@ -1666,21 +1663,24 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
89 
90     if (!xmlBufIsEmpty(buf)) {
91 	node = xmlNewDocText(doc, NULL);
92-        if (node == NULL) {
93-            xmlBufFree(buf);
94-            return(NULL);
95-        }
96+        if (node == NULL)
97+            goto out;
98 	node->content = xmlBufDetach(buf);
99 
100 	if (last == NULL) {
101-	    ret = node;
102+	    head = node;
103 	} else {
104 	    xmlAddNextSibling(last, node);
105 	}
106     }
107 
108+    ret = head;
109+    head = NULL;
110+
111 out:
112     xmlBufFree(buf);
113+    if (val != NULL) xmlFree(val);
114+    if (head != NULL) xmlFreeNodeList(head);
115     return(ret);
116 }
117 
118-- 
1192.27.0
120
121