Version in base suite: 2.12.7+dfsg+really2.9.14-2.1+deb13u2 Base version: libxml2_2.12.7+dfsg+really2.9.14-2.1+deb13u2 Target version: libxml2_2.12.7+dfsg+really2.9.14-2.1+deb13u3 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libx/libxml2/libxml2_2.12.7+dfsg+really2.9.14-2.1+deb13u2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libx/libxml2/libxml2_2.12.7+dfsg+really2.9.14-2.1+deb13u3.dsc changelog | 32 + libxml2.symbols | 2 patches/0030-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch | 21 patches/0035-testcatalog-Add-new-tests-for-catalog.c.patch | 306 +++++++++ patches/0037-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch | 22 patches/0038-fix-memory-leak-in-issue-1054.patch | 44 + patches/0039-schematron-fix-additional-memory-leaks-on-error-path.patch | 51 + patches/0040-catalog-fix-stack-overflow-from-self-referencing-SGM.patch | 45 + patches/CVE-2025-49794_49796.patch | 31 - patches/CVE-2025-8732.patch | 149 ++++ patches/CVE-2026-0989.patch | 308 ++++++++++ patches/CVE-2026-0990.patch | 74 ++ patches/CVE-2026-0992/01-4af23b523.patch | 47 + patches/CVE-2026-0992/02-096402c94.patch | 31 + patches/CVE-2026-1757.patch | 34 + patches/series | 12 salsa-ci.yml | 8 17 files changed, 1213 insertions(+), 4 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpi2xpdoob/libxml2_2.12.7+dfsg+really2.9.14-2.1+deb13u2.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpi2xpdoob/libxml2_2.12.7+dfsg+really2.9.14-2.1+deb13u3.dsc: no acceptable signature found diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/changelog libxml2-2.12.7+dfsg+really2.9.14/debian/changelog --- libxml2-2.12.7+dfsg+really2.9.14/debian/changelog 2025-10-11 12:55:59.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/changelog 2026-06-07 17:02:23.000000000 +0000 @@ -1,3 +1,35 @@ +libxml2 (2.12.7+dfsg+really2.9.14-2.1+deb13u3) trixie; urgency=high + + * Non-maintainer upload. + * Fix CVE-2026-0989: Specially crafted or overly complex schemas can cause + excessive recursion during parsing, which may lead to stack exhaustion and + application crashes. The parser now enforces a limit on inclusion depth + when resolving nested `` directives; the limit defaults to 1000 + and can be modified at runtime with the env variable `RNG_INCLUDE_LIMIT`. + (Closes: #1125691) + * Fix CVE-2026-0990: `xmlCatalogXMLResolveURI()` will recurse infinitely if + a catalog has a URI delegate referencing itself, eventually resulting in a + call stack overflow. (Closes: #1125695) + * Fix CVE-2026-0992: Denial of Service vulnerability due to uncontrolled + resource consumption when processing XML catalogs containing repeated + `` elements pointing to the same downstream catalog. + (Closes: #1125696) + * Fix CVE-2025-8732: When a catalog file contains a CATALOG directive + pointing to itself, `xmlExpandCatalog()` and `xmlParseSGMLCatalog()` + recursively call each other without bounds until stack overflow. + * Fix CVE-2026-1757: Memory leak issue in the command parsing logic of the + xmllint interactive shell. + * Fix unit tests for CVE-2025-49794 and -49796. + * Backport some more upstream changes from v2.15.2: + + Fix memory leak of prefix in `xmlTextWriterStartElementNS()`. + + Mitigate use-after-free issue in `xmlRelaxNGValidateValue()`. + + Fix memory leak in `xmlTextWriterStartAttributeNS()`. + + Schematron: Fix additional memory leaks on error paths. + + Catalog: Fix stack overflow from self-referencing SGML CATALOG entries. + * Add d/salsa-ci.yml for Salsa CI. + + -- Guilhem Moulin Sun, 07 Jun 2026 19:02:23 +0200 + libxml2 (2.12.7+dfsg+really2.9.14-2.1+deb13u2) trixie; urgency=high * Non-maintainer upload. diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/libxml2.symbols libxml2-2.12.7+dfsg+really2.9.14/debian/libxml2.symbols --- libxml2-2.12.7+dfsg+really2.9.14/debian/libxml2.symbols 2025-10-11 12:55:59.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/libxml2.symbols 2026-06-07 17:02:23.000000000 +0000 @@ -138,6 +138,7 @@ xmlBufWriteQuotedString@Base 2.9.0 xmlBufferDetach@LIBXML2_2.8.0 2.8.0 xmlBuildRelativeURI@LIBXML2_2.6.11 2.8.0 + xmlCatalogDumpDoc@Base 2.12.7+dfsg+really2.9.14-2.1+deb13u3~ xmlCharEncFirstLineInput@Base 2.9.0 xmlCharEncFirstLineInt@Base 2.7.4 xmlCharEncInput@Base 2.9.0 @@ -158,6 +159,7 @@ xmlParserInputBufferCreateFilenameDefault@LIBXML2_2.6.11 2.8.0 xmlParserInputBufferCreateFilenameValue@LIBXML2_2.6.11 2.8.0 xmlPopOutputCallbacks@LIBXML2_2.9.11 2.9.11 + xmlRelaxParserSetIncLImit@Base 2.12.7+dfsg+really2.9.14-2.1+deb13u3~ xmlSchemaCollapseString@LIBXML2_2.6.11 2.8.0 xmlSchemaFreeWildcard@LIBXML2_2.6.11 2.8.0 xmlSchemaGetBuiltInListSimpleTypeItemType@LIBXML2_2.6.11 2.8.0 diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0030-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0030-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0030-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0030-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,21 @@ +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Thu, 4 Sep 2025 21:13:24 +0200 +Subject: Fix memory leak of prefix in xmlTextWriterStartElementNS() + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/7d138310f1d4f006d490e29c72168c8ede3a020a +--- + xmlwriter.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/xmlwriter.c b/xmlwriter.c +index 58445c8..49b3012 100644 +--- a/xmlwriter.c ++++ b/xmlwriter.c +@@ -1095,6 +1095,7 @@ xmlTextWriterStartElementNS(xmlTextWriterPtr writer, + if (p->uri == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartElementNS : out of memory!\n"); ++ xmlFree(p->prefix); + xmlFree(p); + return -1; + } diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0035-testcatalog-Add-new-tests-for-catalog.c.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0035-testcatalog-Add-new-tests-for-catalog.c.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0035-testcatalog-Add-new-tests-for-catalog.c.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0035-testcatalog-Add-new-tests-for-catalog.c.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,306 @@ +From: Daniel Garcia Moreno +Date: Fri, 19 Dec 2025 12:27:54 +0100 +Subject: 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 + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/f14c733327f163b49a632f03d05a58c119ed7e57 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/issues/1018 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/issues/1019 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/issues/1040 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-0990 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-0992 +--- + Makefile.am | 8 ++- + catalog.c | 63 +++++++++++++++------- + include/libxml/catalog.h | 2 + + test/catalogs/catalog-recursive.xml | 3 ++ + test/catalogs/repeated-next-catalog.xml | 10 ++++ + testcatalog.c | 96 +++++++++++++++++++++++++++++++++ + 6 files changed, 161 insertions(+), 21 deletions(-) + create mode 100644 test/catalogs/catalog-recursive.xml + create mode 100644 test/catalogs/repeated-next-catalog.xml + create mode 100644 testcatalog.c + +diff --git a/Makefile.am b/Makefile.am +index 7917b59..17b2496 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -12,7 +12,7 @@ AM_CFLAGS = $(EXTRA_CFLAGS) $(THREAD_CFLAGS) $(Z_CFLAGS) $(LZMA_CFLAGS) + + check_PROGRAMS=testSchemas testRelax testSAX testHTML testXPath testURI \ + testThreads testC14N testAutomata testRegexp \ +- testReader testapi testModule runtest runsuite testchar \ ++ testReader testapi testcatalog testModule runtest runsuite testchar \ + testdict runxmlconf testrecurse testlimits + + bin_PROGRAMS = xmllint xmlcatalog +@@ -81,6 +81,10 @@ testlimits_LDFLAGS = + testlimits_DEPENDENCIES = $(DEPS) + testlimits_LDADD= $(BASE_THREAD_LIBS) $(RDL_LIBS) $(LDADDS) + ++testcatalog_SOURCES=testcatalog.c ++testcatalog_DEPENDENCIES = $(DEPS) ++testcatalog_LDADD= $(LDADDS) ++ + testchar_SOURCES=testchar.c + testchar_LDFLAGS = + testchar_DEPENDENCIES = $(DEPS) +@@ -198,7 +202,7 @@ runxmlconf_LDADD= $(LDADDS) + #testOOM_DEPENDENCIES = $(DEPS) + #testOOM_LDADD= $(LDADDS) + +-runtests: runtest$(EXEEXT) testrecurse$(EXEEXT) testapi$(EXEEXT) \ ++runtests: runtest$(EXEEXT) testrecurse$(EXEEXT) testapi$(EXEEXT) testcatalog$(EXEEXT) \ + testchar$(EXEEXT) testdict$(EXEEXT) runxmlconf$(EXEEXT) + [ -d test ] || $(LN_S) $(srcdir)/test . + [ -d result ] || $(LN_S) $(srcdir)/result . +diff --git a/catalog.c b/catalog.c +index c211812..df97a67 100644 +--- a/catalog.c ++++ b/catalog.c +@@ -658,43 +658,54 @@ static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog, + } + } + +-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 + */ +@@ -3441,6 +3452,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 */ + + /** +diff --git a/include/libxml/catalog.h b/include/libxml/catalog.h +index 26b178d..a507a87 100644 +--- a/include/libxml/catalog.h ++++ b/include/libxml/catalog.h +@@ -119,6 +119,8 @@ XMLPUBFUN void XMLCALL + #ifdef LIBXML_OUTPUT_ENABLED + XMLPUBFUN void XMLCALL + xmlCatalogDump (FILE *out); ++XMLPUBFUN xmlDocPtr ++ xmlCatalogDumpDoc (void); + #endif /* LIBXML_OUTPUT_ENABLED */ + XMLPUBFUN xmlChar * XMLCALL + xmlCatalogResolve (const xmlChar *pubID, +diff --git a/test/catalogs/catalog-recursive.xml b/test/catalogs/catalog-recursive.xml +new file mode 100644 +index 0000000..3b3d03f +--- /dev/null ++++ b/test/catalogs/catalog-recursive.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +diff --git a/test/catalogs/repeated-next-catalog.xml b/test/catalogs/repeated-next-catalog.xml +new file mode 100644 +index 0000000..76d34c3 +--- /dev/null ++++ b/test/catalogs/repeated-next-catalog.xml +@@ -0,0 +1,10 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/testcatalog.c b/testcatalog.c +new file mode 100644 +index 0000000..86d33bd +--- /dev/null ++++ b/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 ++ */ ++ ++ ++#include "libxml.h" ++#include ++ ++#ifdef LIBXML_CATALOG_ENABLED ++#include ++ ++/* 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 diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0037-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0037-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0037-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0037-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,22 @@ +From: Jayakrishna Menon +Date: Tue, 10 Feb 2026 14:24:15 -0700 +Subject: use duplicating variant in relaxng to mitigate UAF + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/df2ba65f661addfba50bdb7f280d594781249dfc +--- + relaxng.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/relaxng.c b/relaxng.c +index 3c6643e..42effaf 100644 +--- a/relaxng.c ++++ b/relaxng.c +@@ -8963,7 +8963,7 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, + + if ((ret == 0) && (ctxt->state->value != NULL) && + (ctxt->state->value != ctxt->state->endvalue)) { +- VALID_ERR2(XML_RELAXNG_ERR_LISTEXTRA, ++ VALID_ERR2P(XML_RELAXNG_ERR_LISTEXTRA, + ctxt->state->value); + ret = -1; + } diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0038-fix-memory-leak-in-issue-1054.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0038-fix-memory-leak-in-issue-1054.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0038-fix-memory-leak-in-issue-1054.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0038-fix-memory-leak-in-issue-1054.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,44 @@ +From: Yun +Date: Wed, 11 Feb 2026 22:32:12 +0000 +Subject: fix memory leak in issue 1054 + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/8d77ac83082288e6b11259266e0ce56095ecdd69 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/work_items/1054 +--- + xmlwriter.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/xmlwriter.c b/xmlwriter.c +index 49b3012..6d52aa2 100644 +--- a/xmlwriter.c ++++ b/xmlwriter.c +@@ -1872,6 +1872,7 @@ xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer, + if (p == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartAttributeNS : out of memory!\n"); ++ xmlFree(buf); + return -1; + } + +@@ -1880,12 +1881,20 @@ xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer, + if (p->uri == 0) { + xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, + "xmlTextWriterStartAttributeNS : out of memory!\n"); ++ xmlFree(p->prefix); + xmlFree(p); + return -1; + } + p->elem = xmlListFront(writer->nodes); + +- xmlListPushFront(writer->nsstack, p); ++ if (xmlListPushFront(writer->nsstack, p) == 0) { ++ xmlWriterErrMsg(writer, XML_ERR_NO_MEMORY, ++ "xmlTextWriterStartAttributeNS : out of memory!\n"); ++ xmlFree(p->uri); ++ xmlFree(p->prefix); ++ xmlFree(p); ++ return -1; ++ } + } + } + diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0039-schematron-fix-additional-memory-leaks-on-error-path.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0039-schematron-fix-additional-memory-leaks-on-error-path.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0039-schematron-fix-additional-memory-leaks-on-error-path.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0039-schematron-fix-additional-memory-leaks-on-error-path.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,51 @@ +From: ylwango613 <1217816127@qq.com> +Date: Tue, 24 Feb 2026 18:23:50 +0800 +Subject: schematron: fix additional memory leaks on error paths + +In xmlSchematronParseRule, free report when xmlSchematronAddTest fails +in the assert and report blocks. + +In xmlSchematronAddTest, free the compiled XPath expression when +xmlMalloc fails. + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/99bf8af1bb9654dd6746c73456ce17412fe442f3 +--- + schematron.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/schematron.c b/schematron.c +index d90f367..944fc3c 100644 +--- a/schematron.c ++++ b/schematron.c +@@ -331,6 +331,7 @@ xmlSchematronAddTest(xmlSchematronParserCtxtPtr ctxt, + ret = (xmlSchematronTestPtr) xmlMalloc(sizeof(xmlSchematronTest)); + if (ret == NULL) { + xmlSchematronPErrMemory(ctxt, "allocating schema test", node); ++ xmlXPathFreeCompExpr(comp); + return (NULL); + } + memset(ret, 0, sizeof(xmlSchematronTest)); +@@ -906,8 +907,10 @@ xmlSchematronParseRule(xmlSchematronParserCtxtPtr ctxt, + + testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_ASSERT, + ruleptr, cur, test, report); +- if (testptr == NULL) ++ if (testptr == NULL) { + xmlFree(test); ++ xmlFree(report); ++ } + } + } else if (IS_SCHEMATRON(cur, "report")) { + nbChecks++; +@@ -929,8 +932,10 @@ xmlSchematronParseRule(xmlSchematronParserCtxtPtr ctxt, + + testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_REPORT, + ruleptr, cur, test, report); +- if (testptr == NULL) ++ if (testptr == NULL) { + xmlFree(test); ++ xmlFree(report); ++ } + } + } else { + xmlSchematronPErr(ctxt, cur, diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0040-catalog-fix-stack-overflow-from-self-referencing-SGM.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0040-catalog-fix-stack-overflow-from-self-referencing-SGM.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0040-catalog-fix-stack-overflow-from-self-referencing-SGM.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0040-catalog-fix-stack-overflow-from-self-referencing-SGM.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,45 @@ +From: ylwango613 <1217816127@qq.com> +Date: Tue, 24 Feb 2026 20:19:43 +0800 +Subject: catalog: fix stack overflow from self-referencing SGML CATALOG + entries + +An SGML catalog file with multiple CATALOG directives referencing itself +causes exponential recursion in xmlParseSGMLCatalog(), leading to stack +overflow. With K self-referencing entries and MAX_CATAL_DEPTH=50, total +recursive parses = K^50. + +Add deduplication by registering expanded filenames in the catalog hash +table before calling xmlExpandCatalog(), consistent with the existing +super branch. + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/4982ee83f91ed598de793b280c8990646726c440 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/work_items/1064 +--- + catalog.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/catalog.c b/catalog.c +index df97a67..6559a89 100644 +--- a/catalog.c ++++ b/catalog.c +@@ -2559,10 +2559,19 @@ xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value, + } + } else { + xmlChar *filename; ++ xmlCatalogEntryPtr entry; + + filename = xmlBuildURI(sysid, base); + if (filename != NULL) { +- xmlExpandCatalog(catal, (const char *)filename, depth); ++ entry = xmlNewCatalogEntry(type, sysid, NULL, NULL, ++ XML_CATA_PREFER_NONE, NULL); ++ res = xmlHashAddEntry(catal->sgml, filename, entry); ++ if (res < 0) { ++ xmlFreeCatalogEntry(entry, NULL); ++ } else { ++ xmlExpandCatalog(catal, ++ (const char *)filename, depth); ++ } + xmlFree(filename); + } + } diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2025-49794_49796.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2025-49794_49796.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2025-49794_49796.patch 2025-10-11 12:55:59.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2025-49794_49796.patch 2026-06-07 17:02:23.000000000 +0000 @@ -26,19 +26,42 @@ create mode 100644 test/schematron/cve-2025-49796.sct create mode 100644 test/schematron/cve-2025-49796_0.xml +Index: libxml2-2.12.7+dfsg+really2.9.14/result/schematron/cve-2025-49794_0 +=================================================================== +--- /dev/null ++++ libxml2-2.12.7+dfsg+really2.9.14/result/schematron/cve-2025-49794_0 +@@ -0,0 +1,7 @@ ++ ++ ++ ++ ++ ++ ++ Index: libxml2-2.12.7+dfsg+really2.9.14/result/schematron/cve-2025-49794_0.err =================================================================== --- /dev/null +++ libxml2-2.12.7+dfsg+really2.9.14/result/schematron/cve-2025-49794_0.err -@@ -0,0 +1,2 @@ -+./test/schematron/cve-2025-49794_0.xml:2: element boo0: schematron error : /librar0/boo0 line 2: +@@ -0,0 +1,3 @@ ++Pattern: ++/librar0/boo0 line 2: +./test/schematron/cve-2025-49794_0.xml fails to validate +Index: libxml2-2.12.7+dfsg+really2.9.14/result/schematron/cve-2025-49796_0 +=================================================================== +--- /dev/null ++++ libxml2-2.12.7+dfsg+really2.9.14/result/schematron/cve-2025-49796_0 +@@ -0,0 +1,4 @@ ++ ++ ++ ++ Index: libxml2-2.12.7+dfsg+really2.9.14/result/schematron/cve-2025-49796_0.err =================================================================== --- /dev/null +++ libxml2-2.12.7+dfsg+really2.9.14/result/schematron/cve-2025-49796_0.err -@@ -0,0 +1,2 @@ -+./test/schematron/cve-2025-49796_0.xml:2: element boo0: schematron error : /librar0/boo0 line 2: +@@ -0,0 +1,3 @@ ++Pattern: ++/librar0/boo0 line 2: +./test/schematron/cve-2025-49796_0.xml fails to validate Index: libxml2-2.12.7+dfsg+really2.9.14/schematron.c =================================================================== diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2025-8732.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2025-8732.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2025-8732.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2025-8732.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,149 @@ +From: Nathan +Date: Wed, 10 Sep 2025 18:11:50 +0300 +Subject: fix: Prevent infinite recursion in xmlCatalogListXMLResolve + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/3425dece47c8db600f8d7328ae2d7ddfaa0d7b2d +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/issues/958 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2025-8732 +--- + catalog.c | 28 ++++++++++++++++++++-------- + result/catalogs/recursive | 1 + + test/catalogs/recursive.script | 0 + test/catalogs/recursive.sgml | 1 + + 4 files changed, 22 insertions(+), 8 deletions(-) + create mode 100644 result/catalogs/recursive + create mode 100644 test/catalogs/recursive.script + create mode 100644 test/catalogs/recursive.sgml + +diff --git a/catalog.c b/catalog.c +index e071b49..b25a630 100644 +--- a/catalog.c ++++ b/catalog.c +@@ -92,7 +92,7 @@ unsigned long __stdcall GetModuleFileNameA(void*, char*, unsigned long); + #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); + + /************************************************************************ + * * +@@ -2320,6 +2320,7 @@ xmlGetSGMLCatalogEntryType(const xmlChar *name) { + * @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. +@@ -2328,13 +2329,19 @@ xmlGetSGMLCatalogEntryType(const xmlChar *name) { + */ + 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)) { +@@ -2512,7 +2519,7 @@ xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value, + + filename = xmlBuildURI(sysid, base); + if (filename != NULL) { +- xmlExpandCatalog(catal, (const char *)filename); ++ xmlExpandCatalog(catal, (const char *)filename, depth); + xmlFree(filename); + } + } +@@ -2662,7 +2669,7 @@ xmlLoadSGMLSuperCatalog(const char *filename) + return(NULL); + } + +- ret = xmlParseSGMLCatalog(catal, content, filename, 1); ++ ret = xmlParseSGMLCatalog(catal, content, filename, 1, 0); + xmlFree(content); + if (ret < 0) { + xmlFreeCatalog(catal); +@@ -2708,7 +2715,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); +@@ -2731,6 +2738,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 +@@ -2738,13 +2746,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; +@@ -2753,7 +2765,7 @@ xmlExpandCatalog(xmlCatalogPtr catal, const char *filename) + 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); +@@ -3221,7 +3233,7 @@ xmlLoadCatalog(const char *filename) + return(0); + } + +- ret = xmlExpandCatalog(xmlDefaultCatalog, filename); ++ ret = xmlExpandCatalog(xmlDefaultCatalog, filename, 0); + xmlRMutexUnlock(xmlCatalogMutex); + return(ret); + } +diff --git a/result/catalogs/recursive b/result/catalogs/recursive +new file mode 100644 +index 0000000..56ca91e +--- /dev/null ++++ b/result/catalogs/recursive +@@ -0,0 +1 @@ ++> +\ No newline at end of file +diff --git a/test/catalogs/recursive.script b/test/catalogs/recursive.script +new file mode 100644 +index 0000000..e69de29 +diff --git a/test/catalogs/recursive.sgml b/test/catalogs/recursive.sgml +new file mode 100644 +index 0000000..ac2148b +--- /dev/null ++++ b/test/catalogs/recursive.sgml +@@ -0,0 +1 @@ ++CATALOG recursive.sgml diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0989.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0989.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0989.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0989.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,308 @@ +From: Daniel Garcia Moreno +Date: Fri, 10 Oct 2025 09:38:31 +0200 +Subject: Add RelaxNG include limit + +This patch adds a default xmlRelaxNGIncludeLimit of 1.000, and that +limit can be modified at runtime with the env variable +RNG_INCLUDE_LIMIT. + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/66c52b3ac6c32ab112ec2a3bf41e6c30948be113 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/issues/998 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/374 +Bug-Debian-Security: https://deb.freexian.com/extended-lts/tracker/CVE-2026-0989 +Bug-Debian: https://bugs.debian.org/1125691 +--- + include/libxml/relaxng.h | 4 ++ + relaxng.c | 63 ++++++++++++++++++++++++++++-- + runtest.c | 67 ++++++++++++++++++++++++++++++++ + test/relaxng/include/include-limit.rng | 4 ++ + test/relaxng/include/include-limit_1.rng | 4 ++ + test/relaxng/include/include-limit_2.rng | 4 ++ + test/relaxng/include/include-limit_3.rng | 8 ++++ + 7 files changed, 150 insertions(+), 4 deletions(-) + create mode 100644 test/relaxng/include/include-limit.rng + create mode 100644 test/relaxng/include/include-limit_1.rng + create mode 100644 test/relaxng/include/include-limit_2.rng + create mode 100644 test/relaxng/include/include-limit_3.rng + +diff --git a/include/libxml/relaxng.h b/include/libxml/relaxng.h +index f269c9e..d521679 100644 +--- a/include/libxml/relaxng.h ++++ b/include/libxml/relaxng.h +@@ -138,6 +138,10 @@ XMLPUBFUN int XMLCALL + + XMLPUBFUN void XMLCALL + xmlRelaxNGFreeParserCtxt (xmlRelaxNGParserCtxtPtr ctxt); ++XMLPUBFUN int XMLCALL ++ xmlRelaxParserSetIncLImit (xmlRelaxNGParserCtxtPtr ctxt, ++ int limit); ++ + XMLPUBFUN void XMLCALL + xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc err, +diff --git a/relaxng.c b/relaxng.c +index c4c26cb..3c6643e 100644 +--- a/relaxng.c ++++ b/relaxng.c +@@ -18,6 +18,8 @@ + + #ifdef LIBXML_SCHEMAS_ENABLED + ++#include ++#include + #include + #include + #include +@@ -40,6 +42,12 @@ + static const xmlChar *xmlRelaxNGNs = (const xmlChar *) + "http://relaxng.org/ns/structure/1.0"; + ++/* ++ * Default include limit, this can be override with RNG_INCLUDE_LIMIT ++ * env variable ++ */ ++static const int _xmlRelaxNGIncludeLimit = 1000; ++ + #define IS_RELAXNG(node, typ) \ + ((node != NULL) && (node->ns != NULL) && \ + (node->type == XML_ELEMENT_NODE) && \ +@@ -245,6 +253,7 @@ struct _xmlRelaxNGParserCtxt { + int incNr; /* Depth of the include parsing stack */ + int incMax; /* Max depth of the parsing stack */ + xmlRelaxNGIncludePtr *incTab; /* array of incs */ ++ int incLimit; /* Include limit, to avoid stack-overflow on parse */ + + int idref; /* requires idref checking */ + +@@ -1430,6 +1439,23 @@ xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags) + return(0); + } + ++/** ++ * Semi private function used to set the include recursion limit to a ++ * parser context. Set to 0 to use the default value. ++ * ++ * @param ctxt a RelaxNG parser context ++ * @param limit the new include depth limit ++ * @returns 0 if success and -1 in case of error ++ */ ++int ++xmlRelaxParserSetIncLImit(xmlRelaxNGParserCtxtPtr ctxt, int limit) ++{ ++ if (ctxt == NULL) return(-1); ++ if (limit < 0) return(-1); ++ ctxt->incLimit = limit; ++ return(0); ++} ++ + /************************************************************************ + * * + * Document functions * +@@ -1445,7 +1471,7 @@ static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, + * + * Pushes a new include on top of the include stack + * +- * Returns 0 in case of error, the index in the stack otherwise ++ * Returns -1 in case of error, the index in the stack otherwise + */ + static int + xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt, +@@ -1459,9 +1485,15 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt, + sizeof(ctxt->incTab[0])); + if (ctxt->incTab == NULL) { + xmlRngPErrMemory(ctxt, "allocating include\n"); +- return (0); ++ return (-1); + } + } ++ if (ctxt->incNr >= ctxt->incLimit) { ++ xmlRngPErr(ctxt, (xmlNodePtr)value->doc, XML_RNGP_PARSE_ERROR, ++ "xmlRelaxNG: inclusion recursion limit reached\n", NULL, NULL); ++ return(-1); ++ } ++ + if (ctxt->incNr >= ctxt->incMax) { + ctxt->incMax *= 2; + ctxt->incTab = +@@ -1470,7 +1502,7 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt, + sizeof(ctxt->incTab[0])); + if (ctxt->incTab == NULL) { + xmlRngPErrMemory(ctxt, "allocating include\n"); +- return (0); ++ return (-1); + } + } + ctxt->incTab[ctxt->incNr] = value; +@@ -1664,7 +1696,9 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL, + /* + * push it on the stack + */ +- xmlRelaxNGIncludePush(ctxt, ret); ++ if (xmlRelaxNGIncludePush(ctxt, ret) < 0) { ++ return (NULL); ++ } + + /* + * Some preprocessing of the document content, this include recursing +@@ -7511,11 +7545,32 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt) + xmlDocPtr doc; + xmlNodePtr root; + ++ const char *include_limit_env = getenv("RNG_INCLUDE_LIMIT"); ++ + xmlRelaxNGInitTypes(); + + if (ctxt == NULL) + return (NULL); + ++ if (ctxt->incLimit == 0) { ++ ctxt->incLimit = _xmlRelaxNGIncludeLimit; ++ if (include_limit_env != NULL) { ++ char *strEnd; ++ unsigned long val = 0; ++ errno = 0; ++ val = strtoul(include_limit_env, &strEnd, 10); ++ if (errno != 0 || *strEnd != 0 || val > INT_MAX) { ++ xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR, ++ "xmlRelaxNGParse: invalid RNG_INCLUDE_LIMIT %s\n", ++ (const xmlChar*)include_limit_env, ++ NULL); ++ return(NULL); ++ } ++ if (val) ++ ctxt->incLimit = val; ++ } ++ } ++ + /* + * First step is to parse the input document into an DOM/Infoset + */ +diff --git a/runtest.c b/runtest.c +index e6b2cbb..4cd2e18 100644 +--- a/runtest.c ++++ b/runtest.c +@@ -3387,6 +3387,70 @@ rngTest(const char *filename, + return(ret); + } + ++/** ++ * Parse an RNG schemas with a custom RNG_INCLUDE_LIMIT ++ * ++ * @param filename the schemas file ++ * @param result the file with expected result ++ * @param err the file with error messages ++ * @returns 0 in case of success, an error code otherwise ++ */ ++static int ++rngIncludeTest(const char *filename, ++ const char *resul ATTRIBUTE_UNUSED, ++ const char *errr ATTRIBUTE_UNUSED, ++ int options ATTRIBUTE_UNUSED) { ++ xmlRelaxNGParserCtxtPtr ctxt; ++ xmlRelaxNGPtr schemas; ++ int ret = 0; ++ ++ /* first compile the schemas if possible */ ++ ctxt = xmlRelaxNGNewParserCtxt(filename); ++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler, ++ NULL); ++ ++ /* Should work */ ++ schemas = xmlRelaxNGParse(ctxt); ++ if (schemas == NULL) { ++ testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n", ++ filename); ++ ret = -1; ++ goto done; ++ } ++ xmlRelaxNGFree(schemas); ++ xmlRelaxNGFreeParserCtxt(ctxt); ++ ++ ctxt = xmlRelaxNGNewParserCtxt(filename); ++ /* Should fail */ ++ xmlRelaxParserSetIncLImit(ctxt, 2); ++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler, ++ NULL); ++ schemas = xmlRelaxNGParse(ctxt); ++ if (schemas != NULL) { ++ ret = -1; ++ xmlRelaxNGFree(schemas); ++ } ++ xmlRelaxNGFreeParserCtxt(ctxt); ++ ++ ctxt = xmlRelaxNGNewParserCtxt(filename); ++ /* Should work */ ++ xmlRelaxParserSetIncLImit(ctxt, 3); ++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler, ++ NULL); ++ schemas = xmlRelaxNGParse(ctxt); ++ if (schemas == NULL) { ++ testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n", ++ filename); ++ ret = -1; ++ goto done; ++ } ++ xmlRelaxNGFree(schemas); ++ ++done: ++ xmlRelaxNGFreeParserCtxt(ctxt); ++ return(ret); ++} ++ + #ifdef LIBXML_READER_ENABLED + /** + * rngStreamTest: +@@ -4459,6 +4523,9 @@ testDesc testDescriptions[] = { + { "Relax-NG regression tests" , + rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL, + XML_PARSE_DTDATTR | XML_PARSE_NOENT }, ++ { "Relax-NG include limit tests" , ++ rngIncludeTest, "./test/relaxng/include/include-limit.rng", NULL, NULL, NULL, ++ 0 }, + #ifdef LIBXML_READER_ENABLED + { "Relax-NG streaming regression tests" , + rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL, +diff --git a/test/relaxng/include/include-limit.rng b/test/relaxng/include/include-limit.rng +new file mode 100644 +index 0000000..51f0394 +--- /dev/null ++++ b/test/relaxng/include/include-limit.rng +@@ -0,0 +1,4 @@ ++ ++ ++ ++ +diff --git a/test/relaxng/include/include-limit_1.rng b/test/relaxng/include/include-limit_1.rng +new file mode 100644 +index 0000000..4672da3 +--- /dev/null ++++ b/test/relaxng/include/include-limit_1.rng +@@ -0,0 +1,4 @@ ++ ++ ++ ++ +diff --git a/test/relaxng/include/include-limit_2.rng b/test/relaxng/include/include-limit_2.rng +new file mode 100644 +index 0000000..b35ecaa +--- /dev/null ++++ b/test/relaxng/include/include-limit_2.rng +@@ -0,0 +1,4 @@ ++ ++ ++ ++ +diff --git a/test/relaxng/include/include-limit_3.rng b/test/relaxng/include/include-limit_3.rng +new file mode 100644 +index 0000000..86213c6 +--- /dev/null ++++ b/test/relaxng/include/include-limit_3.rng +@@ -0,0 +1,8 @@ ++ ++ ++ ++ ++ ++ ++ ++ diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0990.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0990.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0990.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0990.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,74 @@ +From: Daniel Garcia Moreno +Date: Wed, 17 Dec 2025 15:24:08 +0100 +Subject: catalog: prevent inf recursion in xmlCatalogXMLResolveURI + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/ac6f0fde1476c41f59ad0c68ada3394599ebf2ae +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/issues/1018 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-0990 +Bug-Debian: https://bugs.debian.org/1125695 +--- + catalog.c | 31 +++++++++++++++++++++++-------- + 1 file changed, 23 insertions(+), 8 deletions(-) + +diff --git a/catalog.c b/catalog.c +index b25a630..5eb249e 100644 +--- a/catalog.c ++++ b/catalog.c +@@ -2099,12 +2099,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) { +@@ -2118,21 +2127,27 @@ xmlCatalogListXMLResolveURI(xmlCatalogEntryPtr catal, const xmlChar *URI) { + 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); + } + diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0992/01-4af23b523.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0992/01-4af23b523.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0992/01-4af23b523.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0992/01-4af23b523.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,47 @@ +From: Daniel Garcia Moreno +Date: Fri, 19 Dec 2025 11:02:18 +0100 +Subject: catalog: Ignore repeated nextCatalog entries + +This patch makes the catalog parsing to ignore repeated entries of +nextCatalog with the same value. + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/4af23b523de5b72f27faf3e8e8a99dde5f7b82a2 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/issues/1019 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-0992 +Bug-Debian: https://bugs.debian.org/1125696 +--- + catalog.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/catalog.c b/catalog.c +index 5eb249e..d88ca5d 100644 +--- a/catalog.c ++++ b/catalog.c +@@ -1279,9 +1279,27 @@ xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer, + 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) { diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0992/02-096402c94.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0992/02-096402c94.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0992/02-096402c94.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0992/02-096402c94.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,31 @@ +From: Daniel Garcia Moreno +Date: Sun, 18 Jan 2026 19:47:11 +0100 +Subject: catalog: Do not check value for duplication nextCatalog + +The value field stores the path as it appears in the catalog definition, +the URL is built using xmlBuildURI that changes the relative paths to +absolute. + +This change fixes the issue of using relative path to the same catalog +in the same file. + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/096402c942e9d9a049f283eb4e6da431289900e1 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/issues/1040 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-0992 +Bug-Debian: https://bugs.debian.org/1125696 +--- + catalog.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/catalog.c b/catalog.c +index d88ca5d..c211812 100644 +--- a/catalog.c ++++ b/catalog.c +@@ -1288,7 +1288,6 @@ xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer, + 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) diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-1757.patch libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-1757.patch --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-1757.patch 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-1757.patch 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,34 @@ +From: Daniel Garcia Moreno +Date: Thu, 23 Oct 2025 07:41:19 +0200 +Subject: 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. + +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/5446460ad3229579c91506317fb80ab333d44414 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/issues/1009 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-1757 +--- + debugXML.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/debugXML.c b/debugXML.c +index dfde58e..98e7de0 100644 +--- a/debugXML.c ++++ b/debugXML.c +@@ -2874,8 +2874,11 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, + command[i++] = *cur++; + } + command[i] = 0; +- if (i == 0) ++ if (i == 0) { ++ free(cmdline); ++ cmdline = NULL; + continue; ++ } + + /* + * Parse the argument diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/patches/series libxml2-2.12.7+dfsg+really2.9.14/debian/patches/series --- libxml2-2.12.7+dfsg+really2.9.14/debian/patches/series 2025-10-11 12:55:59.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/series 2026-06-07 17:02:23.000000000 +0000 @@ -26,3 +26,15 @@ CVE-2025-6170.patch CVE-2025-7425.patch CVE-2025-9714.patch +CVE-2026-1757.patch +0030-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch +CVE-2025-8732.patch +CVE-2026-0990.patch +CVE-2026-0992/01-4af23b523.patch +CVE-2026-0992/02-096402c94.patch +0035-testcatalog-Add-new-tests-for-catalog.c.patch +CVE-2026-0989.patch +0037-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch +0038-fix-memory-leak-in-issue-1054.patch +0039-schematron-fix-additional-memory-leaks-on-error-path.patch +0040-catalog-fix-stack-overflow-from-self-referencing-SGM.patch diff -Nru libxml2-2.12.7+dfsg+really2.9.14/debian/salsa-ci.yml libxml2-2.12.7+dfsg+really2.9.14/debian/salsa-ci.yml --- libxml2-2.12.7+dfsg+really2.9.14/debian/salsa-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ libxml2-2.12.7+dfsg+really2.9.14/debian/salsa-ci.yml 2026-06-07 17:02:23.000000000 +0000 @@ -0,0 +1,8 @@ +--- +include: + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml + +variables: + RELEASE: 'trixie' + SALSA_CI_DISABLE_LINTIAN: 1 + SALSA_CI_DISABLE_REPROTEST: 1