From e64653c0e7975594e27d7de2ed4be062c1e4ad03 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Fri, 17 Feb 2023 15:20:33 +0100
Subject: [PATCH] malloc-fail: Fix leak of xmlRegAtom

Found with libFuzzer, see #344.

Reference:https://github.com/GNOME/libxml2/commit/e64653c0e7975594e27d7de2ed4be062c1e4ad03
Conflict:NA
---
 xmlregexp.c | 81 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 55 insertions(+), 26 deletions(-)

diff --git a/xmlregexp.c b/xmlregexp.c
index 8c2ea81..11c684a 100644
--- a/xmlregexp.c
+++ b/xmlregexp.c
@@ -1594,9 +1594,6 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	 * this is a subexpression handling one should not need to
 	 * create a new node except for XML_REGEXP_QUANT_RANGE.
 	 */
-	if (xmlRegAtomPush(ctxt, atom) < 0) {
-	    return(-1);
-	}
 	if ((to != NULL) && (atom->stop != to) &&
 	    (atom->quant != XML_REGEXP_QUANT_RANGE)) {
 	    /*
@@ -1678,8 +1675,10 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 		    copy->max = 0;
 
 		    if (xmlFAGenerateTransitions(ctxt, atom->start, NULL, copy)
-		        < 0)
+		        < 0) {
+                        xmlRegFreeAtom(copy);
 			return(-1);
+                    }
 		    inter = ctxt->state;
 		    counter = xmlRegGetCounter(ctxt);
 		    ctxt->counters[counter].min = atom->min - 1;
@@ -1722,6 +1721,8 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	    default:
 		break;
 	}
+	if (xmlRegAtomPush(ctxt, atom) < 0)
+	    return(-1);
 	return(0);
     }
     if ((atom->min == 0) && (atom->max == 0) &&
@@ -1760,9 +1761,6 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	xmlFAGenerateEpsilonTransition(ctxt, tmp, to);
 	to = tmp;
     }
-    if (xmlRegAtomPush(ctxt, atom) < 0) {
-	return(-1);
-    }
     if ((atom->quant == XML_REGEXP_QUANT_RANGE) &&
         (atom->min == 0) && (atom->max > 0)) {
 	nullable = 1;
@@ -1793,6 +1791,8 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	default:
 	    break;
     }
+    if (xmlRegAtomPush(ctxt, atom) < 0)
+	return(-1);
     return(0);
 }
 
@@ -5447,8 +5447,12 @@ xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr to) {
 	xmlFAGenerateEpsilonTransition(ctxt, previous, to);
     } else {
 	if (xmlFAGenerateTransitions(ctxt, previous,
-	        (CUR=='|' || CUR==')' || CUR==0) ? to : NULL, ctxt->atom) < 0)
+	        (CUR=='|' || CUR==')' || CUR==0) ? to : NULL,
+                ctxt->atom) < 0) {
+            xmlRegFreeAtom(ctxt->atom);
+            ctxt->atom = NULL;
 	    return(-1);
+        }
 	previous = ctxt->state;
 	ctxt->atom = NULL;
     }
@@ -5457,8 +5461,11 @@ xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr to) {
 	if (ret != 0) {
 	    if (xmlFAGenerateTransitions(ctxt, previous,
 	            (CUR=='|' || CUR==')' || CUR==0) ? to : NULL,
-                    ctxt->atom) < 0)
-		    return(-1);
+                    ctxt->atom) < 0) {
+                xmlRegFreeAtom(ctxt->atom);
+                ctxt->atom = NULL;
+                return(-1);
+            }
 	    previous = ctxt->state;
 	    ctxt->atom = NULL;
 	}
@@ -5990,6 +5997,8 @@ xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
 	return(NULL);
     if ((token2 == NULL) || (*token2 == 0)) {
 	atom->valuep = xmlStrdup(token);
+        if (atom->valuep == NULL)
+            goto error;
     } else {
 	int lenn, lenp;
 	xmlChar *str;
@@ -5998,10 +6007,8 @@ xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
 	lenp = strlen((char *) token);
 
 	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
-	if (str == NULL) {
-	    xmlRegFreeAtom(atom);
-	    return(NULL);
-	}
+	if (str == NULL)
+	    goto error;
 	memcpy(&str[0], token, lenp);
 	str[lenp] = '|';
 	memcpy(&str[lenp + 1], token2, lenn);
@@ -6027,10 +6034,11 @@ xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
     if (to == NULL) {
 	to = xmlRegStatePush(am);
         if (to == NULL)
-            return(NULL);
+            goto error;
     }
     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
-    xmlRegAtomPush(am, atom);
+    if (xmlRegAtomPush(am, atom) < 0)
+        goto error;
     am->state = to;
 
     if (to == NULL)
@@ -6040,6 +6048,10 @@ xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
     if (min == 0)
 	xmlFAGenerateEpsilonTransition(am, from, to);
     return(to);
+
+error:
+    xmlRegFreeAtom(atom);
+    return(NULL);
 }
 
 /**
@@ -6076,6 +6088,8 @@ xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
     if (atom == NULL)
 	return(NULL);
     atom->valuep = xmlStrdup(token);
+    if (atom->valuep == NULL)
+        goto error;
     atom->data = data;
     if (min == 0)
 	atom->min = 1;
@@ -6094,10 +6108,11 @@ xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
     if (to == NULL) {
 	to = xmlRegStatePush(am);
         if (to == NULL)
-            return(NULL);
+            goto error;
     }
     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
-    xmlRegAtomPush(am, atom);
+    if (xmlRegAtomPush(am, atom) < 0)
+        goto error;
     am->state = to;
 
     if (to == NULL)
@@ -6107,6 +6122,10 @@ xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
     if (min == 0)
 	xmlFAGenerateEpsilonTransition(am, from, to);
     return(to);
+
+error:
+    xmlRegFreeAtom(atom);
+    return(NULL);
 }
 
 /**
@@ -6147,6 +6166,8 @@ xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
 	return(NULL);
     if ((token2 == NULL) || (*token2 == 0)) {
 	atom->valuep = xmlStrdup(token);
+        if (atom->valuep == NULL)
+            goto error;
     } else {
 	int lenn, lenp;
 	xmlChar *str;
@@ -6155,10 +6176,8 @@ xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
 	lenp = strlen((char *) token);
 
 	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
-	if (str == NULL) {
-	    xmlRegFreeAtom(atom);
-	    return(NULL);
-	}
+	if (str == NULL)
+	    goto error;
 	memcpy(&str[0], token, lenp);
 	str[lenp] = '|';
 	memcpy(&str[lenp + 1], token2, lenn);
@@ -6181,12 +6200,17 @@ xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
     if (to == NULL) {
 	to = xmlRegStatePush(am);
         if (to == NULL)
-            return(NULL);
+            goto error;
     }
     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
-    xmlRegAtomPush(am, atom);
+    if (xmlRegAtomPush(am, atom) < 0)
+        goto error;
     am->state = to;
     return(to);
+
+error:
+    xmlRegFreeAtom(atom);
+    return(NULL);
 }
 
 
@@ -6241,12 +6265,17 @@ xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
     if (to == NULL) {
 	to = xmlRegStatePush(am);
         if (to == NULL)
-            return(NULL);
+            goto error;
     }
     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
-    xmlRegAtomPush(am, atom);
+    if (xmlRegAtomPush(am, atom) < 0)
+        goto error;
     am->state = to;
     return(to);
+
+error:
+    xmlRegFreeAtom(atom);
+    return(NULL);
 }
 
 /**
-- 
2.27.0

