File libxml2-CVE-2025-8732.patch of Package libxml2

From eae9291aa73907694dd3a4274d306e31217e746e Mon Sep 17 00:00:00 2001
From: Nathan <nathan.shain@echohq.com>
Date: Wed, 10 Sep 2025 18:11:50 +0300
Subject: [PATCH] fix: Prevent infinite recursion in xmlCatalogListXMLResolve

---
 catalog.c                      | 29 +++++++++++++++++++++--------
 result/catalogs/recursive      |  1 +
 test/catalogs/recursive.script |  0
 test/catalogs/recursive.sgml   |  1 +
 4 files changed, 23 insertions(+), 8 deletions(-)
 create mode 100644 result/catalogs/recursive
 create mode 100644 test/catalogs/recursive.script
 create mode 100644 test/catalogs/recursive.sgml

Index: libxml2-2.14.5/catalog.c
===================================================================
--- libxml2-2.14.5.orig/catalog.c
+++ libxml2-2.14.5/catalog.c
@@ -62,7 +62,7 @@
 #endif
 
 static xmlChar *xmlCatalogNormalizePublic(const xmlChar *pubID);
-static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename);
+static int xmlExpandCatalog(xmlCatalogPtr catal, const char *filename, int depth);
 
 /************************************************************************
  *									*
@@ -2275,6 +2275,7 @@ xmlGetSGMLCatalogEntryType(const xmlChar
  * @file:  the filepath for the catalog
  * @super:  should this be handled as a Super Catalog in which case
  *          parsing is not recursive
+ * @depth:  the current depth of the catalog
  *
  * Parse an SGML catalog content and fill up the @catal hash table with
  * the new entries found.
@@ -2283,13 +2284,19 @@ xmlGetSGMLCatalogEntryType(const xmlChar
  */
 static int
 xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
-	            const char *file, int super) {
+	            const char *file, int super, int depth) {
     const xmlChar *cur = value;
     xmlChar *base = NULL;
     int res;
 
     if ((cur == NULL) || (file == NULL))
         return(-1);
+
+    /* Check recursion depth */
+    if (depth > MAX_CATAL_DEPTH) {
+        return(-1);
+    }
+
     base = xmlStrdup((const xmlChar *) file);
 
     while ((cur != NULL) && (cur[0] != 0)) {
@@ -2467,7 +2474,7 @@ xmlParseSGMLCatalog(xmlCatalogPtr catal,
 
 		    filename = xmlBuildURI(sysid, base);
 		    if (filename != NULL) {
-			xmlExpandCatalog(catal, (const char *)filename);
+			xmlExpandCatalog(catal, (const char *)filename, depth);
 			xmlFree(filename);
 		    }
 		}
@@ -2617,7 +2624,7 @@ xmlLoadSGMLSuperCatalog(const char *file
 	return(NULL);
     }
 
-    ret = xmlParseSGMLCatalog(catal, content, filename, 1);
+    ret = xmlParseSGMLCatalog(catal, content, filename, 1, 0);
     xmlFree(content);
     if (ret < 0) {
 	xmlFreeCatalog(catal);
@@ -2663,7 +2670,7 @@ xmlLoadACatalog(const char *filename)
 	    xmlFree(content);
 	    return(NULL);
 	}
-        ret = xmlParseSGMLCatalog(catal, content, filename, 0);
+        ret = xmlParseSGMLCatalog(catal, content, filename, 0, 0);
 	if (ret < 0) {
 	    xmlFreeCatalog(catal);
 	    xmlFree(content);
@@ -2686,6 +2693,7 @@ xmlLoadACatalog(const char *filename)
  * xmlExpandCatalog:
  * @catal:  a catalog
  * @filename:  a file path
+ * @depth:  the current depth of the catalog
  *
  * Load the catalog and expand the existing catal structure.
  * This can be either an XML Catalog or an SGML Catalog
@@ -2693,13 +2701,17 @@ xmlLoadACatalog(const char *filename)
  * Returns 0 in case of success, -1 in case of error
  */
 static int
-xmlExpandCatalog(xmlCatalogPtr catal, const char *filename)
+xmlExpandCatalog(xmlCatalogPtr catal, const char *filename, int depth)
 {
     int ret;
 
     if ((catal == NULL) || (filename == NULL))
 	return(-1);
 
+    /* Check recursion depth */
+    if (depth > MAX_CATAL_DEPTH) {
+		return(-1);
+    }
 
     if (catal->type == XML_SGML_CATALOG_TYPE) {
 	xmlChar *content;
@@ -2708,7 +2720,7 @@ xmlExpandCatalog(xmlCatalogPtr catal, co
 	if (content == NULL)
 	    return(-1);
 
-        ret = xmlParseSGMLCatalog(catal, content, filename, 0);
+        ret = xmlParseSGMLCatalog(catal, content, filename, 0, depth + 1);
 	if (ret < 0) {
 	    xmlFree(content);
 	    return(-1);
@@ -3142,7 +3154,7 @@ xmlLoadCatalog(const char *filename)
 	return(0);
     }
 
-    ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
+    ret = xmlExpandCatalog(xmlDefaultCatalog, filename, 0);
     xmlRMutexUnlock(&xmlCatalogMutex);
     return(ret);
 }
Index: libxml2-2.14.5/result/catalogs/recursive
===================================================================
--- /dev/null
+++ libxml2-2.14.5/result/catalogs/recursive
@@ -0,0 +1 @@
+> 
\ No newline at end of file
Index: libxml2-2.14.5/test/catalogs/recursive.sgml
===================================================================
--- /dev/null
+++ libxml2-2.14.5/test/catalogs/recursive.sgml
@@ -0,0 +1 @@
+CATALOG recursive.sgml
openSUSE Build Service is sponsored by