1 Commits

Author SHA256 Message Date
1a028b25ee Fix multiple CVEs 2026-02-13 23:21:28 +01:00
7 changed files with 808 additions and 7 deletions

View File

@@ -0,0 +1,127 @@
From 0e50b31902cdb1eb242eb361c123e9e033b2af87 Mon Sep 17 00:00:00 2001
From: Daniel Garcia Moreno <daniel.garcia@suse.com>
Date: Wed, 8 Oct 2025 09:18:51 +0200
Subject: [PATCH] Ignore next/prev of documents when traversing XPath
See https://gitlab.gnome.org/GNOME/libxml2/-/issues/996
---
xpath.c | 66 ++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 49 insertions(+), 17 deletions(-)
Index: libxml2-2.14.5/xpath.c
===================================================================
--- libxml2-2.14.5.orig/xpath.c
+++ libxml2-2.14.5/xpath.c
@@ -6814,12 +6814,18 @@ xmlNodePtr
xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
- (ctxt->context->node->type == XML_NAMESPACE_DECL))
- return(NULL);
+ (ctxt->context->node->type == XML_NAMESPACE_DECL))
+ return(NULL);
+
if (cur == (xmlNodePtr) ctxt->context->doc)
return(NULL);
+
if (cur == NULL)
- return(ctxt->context->node->next);
+ cur = ctxt->context->node;
+
+ if (cur->type == XML_DOCUMENT_NODE)
+ return(NULL);
+
return(cur->next);
}
@@ -6839,17 +6845,23 @@ xmlNodePtr
xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
- (ctxt->context->node->type == XML_NAMESPACE_DECL))
- return(NULL);
+ (ctxt->context->node->type == XML_NAMESPACE_DECL))
+ return(NULL);
+
if (cur == (xmlNodePtr) ctxt->context->doc)
return(NULL);
- if (cur == NULL)
- return(ctxt->context->node->prev);
- if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) {
- cur = cur->prev;
- if (cur == NULL)
- return(ctxt->context->node->prev);
+
+ if (cur == NULL) {
+ cur = ctxt->context->node;
+ } else if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) {
+ cur = cur->prev;
+ if (cur == NULL)
+ cur = ctxt->context->node;
}
+
+ if (cur->type == XML_DOCUMENT_NODE)
+ return(NULL);
+
return(cur->prev);
}
@@ -6886,14 +6898,27 @@ xmlXPathNextFollowing(xmlXPathParserCont
cur = (xmlNodePtr) ns->next;
}
}
- if (cur == NULL) return(NULL) ; /* ERROR */
- if (cur->next != NULL) return(cur->next) ;
+
+ /* ERROR */
+ if (cur == NULL)
+ return(NULL);
+
+ if (cur->type == XML_DOCUMENT_NODE)
+ return(NULL);
+
+ if (cur->next != NULL)
+ return(cur->next);
+
do {
cur = cur->parent;
- if (cur == NULL) break;
- if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL);
- if (cur->next != NULL) return(cur->next);
+ if (cur == NULL)
+ break;
+ if (cur == (xmlNodePtr) ctxt->context->doc)
+ return(NULL);
+ if (cur->next != NULL && cur->type != XML_DOCUMENT_NODE)
+ return(cur->next);
} while (cur != NULL);
+
return(cur);
}
@@ -7011,10 +7036,13 @@ xmlXPathNextPrecedingInternal(xmlXPathPa
}
ctxt->ancestor = cur->parent;
}
- if (cur->type == XML_NAMESPACE_DECL)
+
+ if (cur->type == XML_NAMESPACE_DECL || cur->type == XML_DOCUMENT_NODE)
return(NULL);
+
if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
cur = cur->prev;
+
while (cur->prev == NULL) {
cur = cur->parent;
if (cur == NULL)
@@ -7025,6 +7053,10 @@ xmlXPathNextPrecedingInternal(xmlXPathPa
return (cur);
ctxt->ancestor = cur->parent;
}
+
+ if (cur->type == XML_DOCUMENT_NODE)
+ return(NULL);
+
cur = cur->prev;
while (cur->last != NULL)
cur = cur->last;

142
libxml2-CVE-2025-8732.patch Normal file
View File

@@ -0,0 +1,142 @@
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.13.8/catalog.c
===================================================================
--- libxml2-2.13.8.orig/catalog.c
+++ libxml2-2.13.8/catalog.c
@@ -60,7 +60,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);
/************************************************************************
* *
@@ -2279,6 +2279,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.
@@ -2287,13 +2288,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)) {
@@ -2471,7 +2478,7 @@ xmlParseSGMLCatalog(xmlCatalogPtr catal,
filename = xmlBuildURI(sysid, base);
if (filename != NULL) {
- xmlExpandCatalog(catal, (const char *)filename);
+ xmlExpandCatalog(catal, (const char *)filename, depth);
xmlFree(filename);
}
}
@@ -2621,7 +2628,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);
@@ -2667,7 +2674,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);
@@ -2690,6 +2697,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
@@ -2697,13 +2705,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;
@@ -2712,7 +2724,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);
@@ -3154,7 +3166,7 @@ xmlLoadCatalog(const char *filename)
return(0);
}
- ret = xmlExpandCatalog(xmlDefaultCatalog, filename);
+ ret = xmlExpandCatalog(xmlDefaultCatalog, filename, 0);
xmlRMutexUnlock(xmlCatalogMutex);
return(ret);
}
Index: libxml2-2.13.8/result/catalogs/recursive
===================================================================
--- /dev/null
+++ libxml2-2.13.8/result/catalogs/recursive
@@ -0,0 +1 @@
+>
\ No newline at end of file
Index: libxml2-2.13.8/test/catalogs/recursive.sgml
===================================================================
--- /dev/null
+++ libxml2-2.13.8/test/catalogs/recursive.sgml
@@ -0,0 +1 @@
+CATALOG recursive.sgml

View File

@@ -0,0 +1,99 @@
From 1961208e958ca22f80a0b4e4c9d71cfa050aa982 Mon Sep 17 00:00:00 2001
From: Daniel Garcia Moreno <daniel.garcia@suse.com>
Date: Wed, 17 Dec 2025 15:24:08 +0100
Subject: [PATCH 1/2] catalog: prevent inf recursion in xmlCatalogXMLResolveURI
Fix https://gitlab.gnome.org/GNOME/libxml2/-/issues/1018
---
catalog.c | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)
Index: libxml2-2.13.8/catalog.c
===================================================================
--- libxml2-2.13.8.orig/catalog.c
+++ libxml2-2.13.8/catalog.c
@@ -1240,9 +1240,26 @@ xmlParseXMLCatalogNode(xmlNodePtr cur, x
BAD_CAST "delegateURI", BAD_CAST "uriStartString",
BAD_CAST "catalog", prefer, cgroup);
} else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) {
+ xmlCatalogEntryPtr prev = parent->children;
+
entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG,
BAD_CAST "nextCatalog", NULL,
BAD_CAST "catalog", prefer, cgroup);
+ /* Avoid duplication of nextCatalog */
+ while (prev != NULL) {
+ if ((prev->type == XML_CATA_NEXT_CATALOG) &&
+ (xmlStrEqual (prev->URL, entry->URL)) &&
+ (xmlStrEqual (prev->value, entry->value)) &&
+ (prev->prefer == entry->prefer) &&
+ (prev->group == entry->group)) {
+ if (xmlDebugCatalogs)
+ fprintf(stderr, "Ignoring repeated nextCatalog %s\n", entry->URL);
+ xmlFreeCatalogEntry(entry, NULL);
+ entry = NULL;
+ break;
+ }
+ prev = prev->next;
+ }
}
if (entry != NULL) {
if (parent != NULL) {
@@ -2060,12 +2077,21 @@ static xmlChar *
xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) {
xmlChar *ret = NULL;
xmlChar *urnID = NULL;
+ xmlCatalogEntryPtr cur = NULL;
if (catal == NULL)
return(NULL);
if (URI == NULL)
return(NULL);
+ if (catal->depth > MAX_CATAL_DEPTH) {
+ xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
+ "Detected recursion in catalog %s\n",
+ catal->name, NULL, NULL);
+ return(NULL);
+ }
+ catal->depth++;
+
if (!xmlStrncmp(URI, BAD_CAST XML_URN_PUBID, sizeof(XML_URN_PUBID) - 1)) {
urnID = xmlCatalogUnWrapURN(URI);
if (xmlDebugCatalogs) {
@@ -2079,21 +2105,27 @@ xmlCatalogListXMLResolveURI(xmlCatalogEn
ret = xmlCatalogListXMLResolve(catal, urnID, NULL);
if (urnID != NULL)
xmlFree(urnID);
+ catal->depth--;
return(ret);
}
- while (catal != NULL) {
- if (catal->type == XML_CATA_CATALOG) {
- if (catal->children == NULL) {
- xmlFetchXMLCatalogFile(catal);
+ cur = catal;
+ while (cur != NULL) {
+ if (cur->type == XML_CATA_CATALOG) {
+ if (cur->children == NULL) {
+ xmlFetchXMLCatalogFile(cur);
}
- if (catal->children != NULL) {
- ret = xmlCatalogXMLResolveURI(catal->children, URI);
- if (ret != NULL)
+ if (cur->children != NULL) {
+ ret = xmlCatalogXMLResolveURI(cur->children, URI);
+ if (ret != NULL) {
+ catal->depth--;
return(ret);
+ }
}
}
- catal = catal->next;
+ cur = cur->next;
}
+
+ catal->depth--;
return(ret);
}

350
libxml2-CVE-2026-0992.patch Normal file
View File

@@ -0,0 +1,350 @@
From f8399e62a31095bf1ced01827c33f9b29494046f Mon Sep 17 00:00:00 2001
From: Daniel Garcia Moreno <daniel.garcia@suse.com>
Date: Fri, 19 Dec 2025 12:27:54 +0100
Subject: [PATCH 1/2] testcatalog: Add new tests for catalog.c
Adds a new test program to run specific tests related to catalog
parsing.
This initial version includes a couple of tests, the first one to check
the infinite recursion detection related to:
https://gitlab.gnome.org/GNOME/libxml2/-/issues/1018.
The second one tests the nextCatalog element repeated parsing, related
to:
https://gitlab.gnome.org/GNOME/libxml2/-/issues/1019
https://gitlab.gnome.org/GNOME/libxml2/-/issues/1040
---
CMakeLists.txt | 2 +
Makefile.am | 6 ++
catalog.c | 63 +++++++++++-----
include/libxml/catalog.h | 2 +
meson.build | 1 +
test/catalogs/catalog-recursive.xml | 3 +
test/catalogs/repeated-next-catalog.xml | 10 +++
testcatalog.c | 96 +++++++++++++++++++++++++
8 files changed, 164 insertions(+), 19 deletions(-)
create mode 100644 test/catalogs/catalog-recursive.xml
create mode 100644 test/catalogs/repeated-next-catalog.xml
create mode 100644 testcatalog.c
Index: libxml2-2.13.8/CMakeLists.txt
===================================================================
--- libxml2-2.13.8.orig/CMakeLists.txt
+++ libxml2-2.13.8/CMakeLists.txt
@@ -505,6 +505,7 @@ if(LIBXML2_WITH_TESTS)
runxmlconf
runsuite
testapi
+ testcatalog
testchar
testdict
testModule
@@ -531,6 +532,7 @@ if(LIBXML2_WITH_TESTS)
if(NOT WIN32)
add_test(NAME testapi COMMAND testapi)
endif()
+ add_test(NAME testcatalog COMMAND testcatalog)
add_test(NAME testchar COMMAND testchar)
add_test(NAME testdict COMMAND testdict)
add_test(NAME testparser COMMAND testparser WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
Index: libxml2-2.13.8/Makefile.am
===================================================================
--- libxml2-2.13.8.orig/Makefile.am
+++ libxml2-2.13.8/Makefile.am
@@ -21,6 +21,7 @@ check_PROGRAMS = \
testModule \
testThreads \
testapi \
+ testcatalog \
testchar \
testdict \
testlimits \
@@ -129,6 +130,10 @@ testlimits_SOURCES=testlimits.c
testlimits_DEPENDENCIES = $(DEPS)
testlimits_LDADD= $(LDADDS)
+testcatalog_SOURCES=testcatalog.c
+testcatalog_DEPENDENCIES = $(DEPS)
+testcatalog_LDADD= $(LDADDS)
+
testchar_SOURCES=testchar.c
testchar_DEPENDENCIES = $(DEPS)
testchar_LDADD= $(LDADDS)
@@ -187,6 +192,7 @@ check-local:
$(CHECKER) ./runtest$(EXEEXT)
$(CHECKER) ./testrecurse$(EXEEXT)
$(CHECKER) ./testapi$(EXEEXT)
+ $(CHECKER) ./testcatalog$(EXEEXT)
$(CHECKER) ./testchar$(EXEEXT)
$(CHECKER) ./testdict$(EXEEXT)
$(CHECKER) ./testparser$(EXEEXT)
Index: libxml2-2.13.8/catalog.c
===================================================================
--- libxml2-2.13.8.orig/catalog.c
+++ libxml2-2.13.8/catalog.c
@@ -627,43 +627,54 @@ static void xmlDumpXMLCatalogNode(xmlCat
}
}
-static int
-xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
- int ret;
- xmlDocPtr doc;
+static xmlDocPtr
+xmlDumpXMLCatalogToDoc(xmlCatalogEntryPtr catal) {
xmlNsPtr ns;
xmlDtdPtr dtd;
xmlNodePtr catalog;
- xmlOutputBufferPtr buf;
+ xmlDocPtr doc = xmlNewDoc(NULL);
+ if (doc == NULL) {
+ return(NULL);
+ }
- /*
- * Rebuild a catalog
- */
- doc = xmlNewDoc(NULL);
- if (doc == NULL)
- return(-1);
dtd = xmlNewDtd(doc, BAD_CAST "catalog",
- BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
-BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
+ BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
+ BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL);
if (ns == NULL) {
- xmlFreeDoc(doc);
- return(-1);
+ xmlFreeDoc(doc);
+ return(NULL);
}
catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL);
if (catalog == NULL) {
- xmlFreeNs(ns);
- xmlFreeDoc(doc);
- return(-1);
+ xmlFreeDoc(doc);
+ xmlFreeNs(ns);
+ return(NULL);
}
catalog->nsDef = ns;
xmlAddChild((xmlNodePtr) doc, catalog);
-
xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL);
+ return(doc);
+}
+
+static int
+xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
+ int ret;
+ xmlDocPtr doc;
+ xmlOutputBufferPtr buf;
+
+ /*
+ * Rebuild a catalog
+ */
+ doc = xmlDumpXMLCatalogToDoc(catal);
+ if (doc == NULL) {
+ return(-1);
+ }
+
/*
* reserialize it
*/
@@ -1249,7 +1260,6 @@ xmlParseXMLCatalogNode(xmlNodePtr cur, x
while (prev != NULL) {
if ((prev->type == XML_CATA_NEXT_CATALOG) &&
(xmlStrEqual (prev->URL, entry->URL)) &&
- (xmlStrEqual (prev->value, entry->value)) &&
(prev->prefer == entry->prefer) &&
(prev->group == entry->group)) {
if (xmlDebugCatalogs)
@@ -3375,6 +3385,20 @@ xmlCatalogDump(FILE *out) {
xmlACatalogDump(xmlDefaultCatalog, out);
}
+
+/**
+ * Dump all the global catalog content as a xmlDoc
+ * This function is just for testing/debugging purposes
+ *
+ * @returns The catalog as xmlDoc or NULL if failed, it must be freed by the caller.
+ */
+xmlDocPtr
+xmlCatalogDumpDoc(void) {
+ if (!xmlCatalogInitialized)
+ xmlInitializeCatalog();
+
+ return xmlDumpXMLCatalogToDoc(xmlDefaultCatalog->xml);
+}
#endif /* LIBXML_OUTPUT_ENABLED */
/**
Index: libxml2-2.13.8/include/libxml/catalog.h
===================================================================
--- libxml2-2.13.8.orig/include/libxml/catalog.h
+++ libxml2-2.13.8/include/libxml/catalog.h
@@ -119,6 +119,8 @@ XMLPUBFUN void
#ifdef LIBXML_OUTPUT_ENABLED
XMLPUBFUN void
xmlCatalogDump (FILE *out);
+XMLPUBFUN xmlDocPtr
+ xmlCatalogDumpDoc (void);
#endif /* LIBXML_OUTPUT_ENABLED */
XMLPUBFUN xmlChar *
xmlCatalogResolve (const xmlChar *pubID,
Index: libxml2-2.13.8/meson.build
===================================================================
--- libxml2-2.13.8.orig/meson.build
+++ libxml2-2.13.8/meson.build
@@ -728,6 +728,7 @@ checks = [
# 'testModule',
'testThreads',
'testapi',
+ 'testcatalog',
'testchar',
'testdict',
'testlimits',
Index: libxml2-2.13.8/test/catalogs/catalog-recursive.xml
===================================================================
--- /dev/null
+++ libxml2-2.13.8/test/catalogs/catalog-recursive.xml
@@ -0,0 +1,3 @@
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <delegateURI uriStartString="/foo" catalog="catalog-recursive.xml"/>
+</catalog>
Index: libxml2-2.13.8/test/catalogs/repeated-next-catalog.xml
===================================================================
--- /dev/null
+++ libxml2-2.13.8/test/catalogs/repeated-next-catalog.xml
@@ -0,0 +1,10 @@
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <nextCatalog catalog="registry.xml"/>
+ <nextCatalog catalog="registry.xml"/>
+ <nextCatalog catalog="./registry.xml"/>
+ <nextCatalog catalog="././registry.xml"/>
+ <nextCatalog catalog="./././registry.xml"/>
+ <nextCatalog catalog="./../catalogs/registry.xml"/>
+ <nextCatalog catalog="./../catalogs/./registry.xml"/>
+</catalog>
+
Index: libxml2-2.13.8/testcatalog.c
===================================================================
--- /dev/null
+++ libxml2-2.13.8/testcatalog.c
@@ -0,0 +1,96 @@
+/*
+ * testcatalog.c: C program to run libxml2 catalog.c unit tests
+ *
+ * To compile on Unixes:
+ * cc -o testcatalog `xml2-config --cflags` testcatalog.c `xml2-config --libs` -lpthread
+ *
+ * See Copyright for the status of this software.
+ *
+ * Author: Daniel Garcia <dani@danigm.net>
+ */
+
+
+#include "libxml.h"
+#include <stdio.h>
+
+#ifdef LIBXML_CATALOG_ENABLED
+#include <libxml/catalog.h>
+
+/* Test catalog resolve uri with recursive catalog */
+static int
+testRecursiveDelegateUri(void) {
+ int ret = 0;
+ const char *cat = "test/catalogs/catalog-recursive.xml";
+ const char *entity = "/foo.ent";
+ xmlChar *resolved = NULL;
+
+ xmlInitParser();
+ xmlLoadCatalog(cat);
+
+ /* This should trigger recursive error */
+ resolved = xmlCatalogResolveURI(BAD_CAST entity);
+ if (resolved != NULL) {
+ fprintf(stderr, "CATALOG-FAILURE: Catalog %s entity should fail to resolve\n", entity);
+ ret = 1;
+ }
+ xmlCatalogCleanup();
+
+ return ret;
+}
+
+/* Test parsing repeated NextCatalog */
+static int
+testRepeatedNextCatalog(void) {
+ int ret = 0;
+ int i = 0;
+ const char *cat = "test/catalogs/repeated-next-catalog.xml";
+ const char *entity = "/foo.ent";
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+
+ xmlInitParser();
+
+ xmlLoadCatalog(cat);
+ /* To force the complete recursive load */
+ xmlCatalogResolveURI(BAD_CAST entity);
+ /**
+ * Ensure that the doc doesn't contain the same nextCatalog
+ */
+ doc = xmlCatalogDumpDoc();
+ xmlCatalogCleanup();
+
+ if (doc == NULL) {
+ fprintf(stderr, "CATALOG-FAILURE: Failed to dump the catalog\n");
+ return 1;
+ }
+
+ /* Just the root "catalog" node with a series of nextCatalog */
+ node = xmlDocGetRootElement(doc);
+ node = node->children;
+ for (i=0; node != NULL; node=node->next, i++) {}
+ if (i > 1) {
+ fprintf(stderr, "CATALOG-FAILURE: Found %d nextCatalog entries and should be 1\n", i);
+ ret = 1;
+ }
+
+ xmlFreeDoc(doc);
+
+ return ret;
+}
+
+int
+main(void) {
+ int err = 0;
+
+ err |= testRecursiveDelegateUri();
+ err |= testRepeatedNextCatalog();
+
+ return err;
+}
+#else
+/* No catalog, so everything okay */
+int
+main(void) {
+ return 0;
+}
+#endif
Index: libxml2-2.13.8/configure.ac
===================================================================
--- libxml2-2.13.8.orig/configure.ac
+++ libxml2-2.13.8/configure.ac
@@ -40,7 +40,7 @@ AC_SUBST(LIBXML_VERSION_EXTRA)
VERSION=${LIBXML_VERSION}
-AM_INIT_AUTOMAKE([1.16.3 foreign no-dist-gzip dist-xz])
+AM_INIT_AUTOMAKE([1.15.1 foreign no-dist-gzip dist-xz])
AM_MAINTAINER_MODE([enable])
AM_SILENT_RULES([yes])

View File

@@ -0,0 +1,36 @@
From 160c8a43ba37dfb07ebe6446fbad9d0973d9279d Mon Sep 17 00:00:00 2001
From: Daniel Garcia Moreno <daniel.garcia@suse.com>
Date: Thu, 23 Oct 2025 07:41:19 +0200
Subject: [PATCH] shell: free cmdline before continue
This patch frees the cmdline when it's not empty but it doesn't contain
any actual character.
If the cmdline is just whitespaces or \r and \n, the loop continues
without freeing the cmdline string, so it's a leak.
Fix https://gitlab.gnome.org/GNOME/libxml2/-/issues/1009
---
shell.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/shell.c b/shell.c
index 43024b089..67f61c307 100644
--- a/debugXML.c
+++ b/debugXML.c
@@ -1138,8 +1138,11 @@ xmllintShell(xmlDoc *doc, const char *filename, FILE * output)
command[i++] = *cur++;
}
command[i] = 0;
- if (i == 0)
+ if (i == 0) {
+ free(cmdline);
+ cmdline = NULL;
continue;
+ }
/*
* Parse the argument
--
GitLab

View File

@@ -1,10 +1,37 @@
-------------------------------------------------------------------
Fri Feb 13 12:16:01 UTC 2026 - David Anes <david.anes@suse.com>
- CVE-2026-0990: call stack overflow leading to application crash
due to infinite recursion in `xmlCatalogXMLResolveURI` (bsc#1256807, bsc#1256811)
* Add patch libxml2-CVE-2026-0990.patch
- CVE-2026-0992: excessive resource consumption when processing XML
catalogs due to exponential behavior when handling `<nextCatalog>` elements (bsc#1256808, bsc#1256809, bsc#1256812)
* Add patch libxml2-CVE-2026-0992.patch
- CVE-2025-8732: infinite recursion in catalog parsing functions when processing malformed SGML catalog files (bsc#1247858, bsc#1247850)
* Add patch libxml2-CVE-2025-8732.patch
-------------------------------------------------------------------
Wed Feb 4 13:40:16 UTC 2026 - Petr Gajdos <pgajdos@suse.com>
- CVE-2026-1757: memory leak in the `xmllint` interactive shell (bsc#1257593, bsc#1257594, bsc#1257595)
* Add patch libxml2-CVE-2026-1757.patch
-------------------------------------------------------------------
Wed Feb 4 09:39:12 UTC 2026 - Petr Gajdos <pgajdos@suse.com>
- CVE-2025-10911: use-after-free with key data stored cross-RVT (bsc#1250553)
* Add patch libxml2-CVE-2025-10911.patch
-------------------------------------------------------------------
Thu Jan 22 13:13:34 UTC 2026 - Daniel Garcia <daniel.garcia@suse.com>
- Add patch libxml2-CVE-2026-0989.patch, to fix call stack exhaustion
leading to application crash due to RelaxNG parser not limiting the
recursion depth when resolving `<include>` directives
CVE-2026-0989, bsc#1256805, https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/374
- CVE-2026-0989: call stack exhaustion leading to application crash
due to RelaxNG parser not limiting the recursion depth when
resolving `<include>` directives (bsc#1256804, bsc#1256805, bsc#1256810)
* Add patch libxml2-CVE-2026-0989.patch
* https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/374
-------------------------------------------------------------------
Fri Jul 18 11:12:01 UTC 2025 - pgajdos@suse.com

View File

@@ -43,9 +43,28 @@ Patch0: libxml2-python3-unicode-errors.patch
# PATCH-FIX-UPSTREAM libxml2-python3-string-null-check.patch bsc#1065270 mgorse@suse.com
# https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/15
Patch1: libxml2-python3-string-null-check.patch
# PATCH-FIX-UPSTREAM libxml2-CVE-2026-0989.patch bsc#1256805 daniel.garcia@suse.com
# https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/374
Patch2: libxml2-CVE-2026-0989.patch
# CVE-2025-8732: infinite recursion in catalog parsing functions when processing malformed SGML catalog files (bsc#1247858, bsc#1247850)
# - https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/337
Patch2: libxml2-CVE-2025-8732.patch
# CVE-2026-0989: call stack exhaustion leading to application crash due to RelaxNG parser not limiting the recursion depth when resolving `<include>` directives (bsc#1256804, bsc#1256805, bsc#1256810)
# - https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/374
Patch3: libxml2-CVE-2026-0989.patch
# CVE-2025-10911: use-after-free with key data stored cross-RVT (bsc#1250553)
# - https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/345
Patch4: libxml2-CVE-2025-10911.patch
# CVE-2026-1757: memory leak in the `xmllint` interactive shell (bsc#1257593, bsc#1257594, bsc#1257595)
# - https://gitlab.gnome.org/GNOME/libxml2/-/commit/160c8a43ba37dfb07ebe6446fbad9d0973d9279d
# - https://gitlab.gnome.org/GNOME/libxml2/-/issues/1009
Patch5: libxml2-CVE-2026-1757.patch
# CVE-2026-0990: call stack overflow leading to application crash due to infinite recursion in `xmlCatalogXMLResolveURI` (bsc#1256806, bsc#1256807, bsc#1256811)
# - https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/368
Patch6: libxml2-CVE-2026-0990.patch
# CVE-2026-0992: excessive resource consumption when processing XML catalogs due to exponential behavior when handling `<nextCatalog>` elements (bsc#1256808, bsc#1256809, bsc#1256812)
# - https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/377
Patch7: libxml2-CVE-2026-0992.patch
# IMPORTANT NOTE: remove automake, libtool buildrequires (+ autoreconf in prep section) once CVE-2026-0992 patch is not needed anymore
BuildRequires: automake
BuildRequires: libtool
#
### -- openSUSE patches range from 1000 to 1999 -- ###
@@ -168,6 +187,7 @@ either at parse time or later once the document has been modified.
%prep
%autosetup -p1 -n libxml2-%{version}
autoreconf -ifv # Required by patch for CVE-2026-0992
sed -i '1 s|/usr/bin/env python|/usr/bin/python3|' doc/apibuild.py
%build