[xml/sgml-pkgs] (o)s-pu uploads to fix no-dsa security issues in libxml2

Guilhem Moulin guilhem at debian.org
Sun Jun 7 18:53:28 BST 2026


Hi,

While working on an upload for bullseye LTS I noticed the version of
src:libxml2 currently found in bookworm and trixie are vulnerable to a
few no-dsa (or unimportant) security issues [0].

CVE-2026-6732 has been triaged not to affect stable and older suites, so
I assume a libxml2 DSA is not in the making and prepared (o)s-pu uploads
for the remaining issues.

I attach tested debdiffs; individual commits and tag can be found on the
LTS team fork [1,2].  Debusine output can be found at

    https://debusine.debian.net/debian/developers/work-request/821755/
    https://debusine.debian.net/debian/developers/work-request/820313/

I'll file trixie- and bookworm-pu bugs with these changes and tag them
moreinfo to give you time to object if desired.  I also intend to NMU
libxml2.9 (sid-only transition package per #1112209) so it doesn't fall
behind trixie's libxml2.

The proposed debdiffs also fixes CVE-2025-8732 and CVE-2026-1757 which
are marked as <not-important> in the security tracker; these issues are
trivially fixable in trixie and bookworm so there is IMHO no reason not
to do it in the -pu upload.  In addition, the proposed debdiffs include
backports of security-related changes fixing memory leaks,
use-after-free and stack overflow issues for which no CVE ID was
assigned (yet).

Cheers,
-- 
Guilhem.

[0] https://security-tracker.debian.org/tracker/source-package/libxml2
[1] https://salsa.debian.org/lts-team/packages/libxml2/-/commits/debian/trixie
[2] https://salsa.debian.org/lts-team/packages/libxml2/-/commits/debian/bookworm
-------------- next part --------------
diffstat for libxml2-2.12.7+dfsg+really2.9.14 libxml2-2.12.7+dfsg+really2.9.14

 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(-)

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 14:55:59.000000000 +0200
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/changelog	2026-06-07 19:02:23.000000000 +0200
@@ -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 `<include>` 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
+    `<nextCatalog>` 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 <guilhem at debian.org>  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 14:55:59.000000000 +0200
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/libxml2.symbols	2026-06-07 19:02:23.000000000 +0200
@@ -138,6 +138,7 @@
  xmlBufWriteQuotedString at Base 2.9.0
  xmlBufferDetach at LIBXML2_2.8.0 2.8.0
  xmlBuildRelativeURI at LIBXML2_2.6.11 2.8.0
+ xmlCatalogDumpDoc at Base 2.12.7+dfsg+really2.9.14-2.1+deb13u3~
  xmlCharEncFirstLineInput at Base 2.9.0
  xmlCharEncFirstLineInt at Base 2.7.4
  xmlCharEncInput at Base 2.9.0
@@ -158,6 +159,7 @@
  xmlParserInputBufferCreateFilenameDefault at LIBXML2_2.6.11 2.8.0
  xmlParserInputBufferCreateFilenameValue at LIBXML2_2.6.11 2.8.0
  xmlPopOutputCallbacks at LIBXML2_2.9.11 2.9.11
+ xmlRelaxParserSetIncLImit at Base 2.12.7+dfsg+really2.9.14-2.1+deb13u3~
  xmlSchemaCollapseString at LIBXML2_2.6.11 2.8.0
  xmlSchemaFreeWildcard at LIBXML2_2.6.11 2.8.0
  xmlSchemaGetBuiltInListSimpleTypeItemType at 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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0030-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,21 @@
+From: Niels Dossche <7771979+nielsdos at 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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0035-testcatalog-Add-new-tests-for-catalog.c.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,306 @@
+From: Daniel Garcia Moreno <daniel.garcia at suse.com>
+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 @@
++<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
++    <delegateURI uriStartString="/foo" catalog="catalog-recursive.xml"/>
++</catalog>
+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 @@
++<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>
++
+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 <dani at 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
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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0037-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,22 @@
+From: Jayakrishna Menon <jkrshnmenon at gmail.com>
+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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0038-fix-memory-leak-in-issue-1054.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,44 @@
+From: Yun <emptyiscolor at gmail.com>
+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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0039-schematron-fix-additional-memory-leaks-on-error-path.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,51 @@
+From: ylwango613 <1217816127 at 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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/0040-catalog-fix-stack-overflow-from-self-referencing-SGM.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,45 @@
+From: ylwango613 <1217816127 at 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 14:55:59.000000000 +0200
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2025-49794_49796.patch	2026-06-07 19:02:23.000000000 +0200
@@ -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 @@
++<?xml version="1.0"?>
++<librar0>
++    <boo0 t="">
++        <author/>
++    </boo0>
++    <ins/>
++</librar0>
 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 @@
++<?xml version="1.0"?>
++<librar0>
++    <boo0/>
++</librar0>
 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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2025-8732.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,149 @@
+From: Nathan <nathan.shain at echohq.com>
+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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0989.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,308 @@
+From: Daniel Garcia Moreno <daniel.garcia at suse.com>
+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 <errno.h>
++#include <stdlib.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <stddef.h>
+@@ -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 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++    <include href="include-limit_1.rng"/>
++</grammar>
+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 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++    <include href="include-limit_2.rng"/>
++</grammar>
+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 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++    <include href="include-limit_3.rng"/>
++</grammar>
+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 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++    <start>
++        <element name="root">
++            <empty/>
++        </element>
++    </start>
++</grammar>
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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0990.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,74 @@
+From: Daniel Garcia Moreno <daniel.garcia at suse.com>
+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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0992/01-4af23b523.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,47 @@
+From: Daniel Garcia Moreno <daniel.garcia at suse.com>
+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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-0992/02-096402c94.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,31 @@
+From: Daniel Garcia Moreno <dani at danigm.net>
+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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/CVE-2026-1757.patch	2026-06-07 19:02:23.000000000 +0200
@@ -0,0 +1,34 @@
+From: Daniel Garcia Moreno <daniel.garcia at suse.com>
+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 14:55:59.000000000 +0200
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/patches/series	2026-06-07 19:02:23.000000000 +0200
@@ -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 01:00:00.000000000 +0100
+++ libxml2-2.12.7+dfsg+really2.9.14/debian/salsa-ci.yml	2026-06-07 19:02:23.000000000 +0200
@@ -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
-------------- next part --------------
diffstat for libxml2-2.9.14+dfsg libxml2-2.9.14+dfsg

 changelog                                                               |   31 +
 libxml2.symbols                                                         |    2 
 patches/0029-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch |   21 
 patches/0034-testcatalog-Add-new-tests-for-catalog.c.patch              |  306 +++++++++
 patches/0036-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch   |   22 
 patches/0037-fix-memory-leak-in-issue-1054.patch                        |   44 +
 patches/0038-schematron-fix-additional-memory-leaks-on-error-path.patch |   51 +
 patches/0039-catalog-fix-stack-overflow-from-self-referencing-SGM.patch |   45 +
 patches/CVE-2025-49794_CVE-2025-49796.patch                             |   29 
 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 
 16 files changed, 1205 insertions(+), 1 deletion(-)

diff -Nru libxml2-2.9.14+dfsg/debian/changelog libxml2-2.9.14+dfsg/debian/changelog
--- libxml2-2.9.14+dfsg/debian/changelog	2025-10-11 14:41:17.000000000 +0200
+++ libxml2-2.9.14+dfsg/debian/changelog	2026-06-07 17:53:53.000000000 +0200
@@ -1,3 +1,34 @@
+libxml2 (2.9.14+dfsg-1.3~deb12u6) bookworm; 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 `<include>` 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
+    `<nextCatalog>` 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.
+
+ -- Guilhem Moulin <guilhem at debian.org>  Sun, 07 Jun 2026 17:53:53 +0200
+
 libxml2 (2.9.14+dfsg-1.3~deb12u5) bookworm; urgency=high
 
   * Non-maintainer upload.
diff -Nru libxml2-2.9.14+dfsg/debian/libxml2.symbols libxml2-2.9.14+dfsg/debian/libxml2.symbols
--- libxml2-2.9.14+dfsg/debian/libxml2.symbols	2025-10-11 14:41:17.000000000 +0200
+++ libxml2-2.9.14+dfsg/debian/libxml2.symbols	2026-06-07 17:53:53.000000000 +0200
@@ -138,6 +138,7 @@
  xmlBufWriteQuotedString at Base 2.9.0
  xmlBufferDetach at LIBXML2_2.8.0 2.8.0
  xmlBuildRelativeURI at LIBXML2_2.6.11 2.8.0
+ xmlCatalogDumpDoc at Base 2.9.14+dfsg-1.3~deb12u6~
  xmlCharEncFirstLineInput at Base 2.9.0
  xmlCharEncFirstLineInt at Base 2.7.4
  xmlCharEncInput at Base 2.9.0
@@ -158,6 +159,7 @@
  xmlParserInputBufferCreateFilenameDefault at LIBXML2_2.6.11 2.8.0
  xmlParserInputBufferCreateFilenameValue at LIBXML2_2.6.11 2.8.0
  xmlPopOutputCallbacks at LIBXML2_2.9.11 2.9.11
+ xmlRelaxParserSetIncLImit at Base 2.9.14+dfsg-1.3~deb12u6~
  xmlSchemaCollapseString at LIBXML2_2.6.11 2.8.0
  xmlSchemaFreeWildcard at LIBXML2_2.6.11 2.8.0
  xmlSchemaGetBuiltInListSimpleTypeItemType at LIBXML2_2.6.11 2.8.0
diff -Nru libxml2-2.9.14+dfsg/debian/patches/0029-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch libxml2-2.9.14+dfsg/debian/patches/0029-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch
--- libxml2-2.9.14+dfsg/debian/patches/0029-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/0029-Fix-memory-leak-of-prefix-in-xmlTextWriterStartEleme.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,21 @@
+From: Niels Dossche <7771979+nielsdos at 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.9.14+dfsg/debian/patches/0034-testcatalog-Add-new-tests-for-catalog.c.patch libxml2-2.9.14+dfsg/debian/patches/0034-testcatalog-Add-new-tests-for-catalog.c.patch
--- libxml2-2.9.14+dfsg/debian/patches/0034-testcatalog-Add-new-tests-for-catalog.c.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/0034-testcatalog-Add-new-tests-for-catalog.c.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,306 @@
+From: Daniel Garcia Moreno <daniel.garcia at suse.com>
+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 @@
++<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
++    <delegateURI uriStartString="/foo" catalog="catalog-recursive.xml"/>
++</catalog>
+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 @@
++<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>
++
+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 <dani at 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
diff -Nru libxml2-2.9.14+dfsg/debian/patches/0036-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch libxml2-2.9.14+dfsg/debian/patches/0036-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch
--- libxml2-2.9.14+dfsg/debian/patches/0036-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/0036-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,22 @@
+From: Jayakrishna Menon <jkrshnmenon at gmail.com>
+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.9.14+dfsg/debian/patches/0037-fix-memory-leak-in-issue-1054.patch libxml2-2.9.14+dfsg/debian/patches/0037-fix-memory-leak-in-issue-1054.patch
--- libxml2-2.9.14+dfsg/debian/patches/0037-fix-memory-leak-in-issue-1054.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/0037-fix-memory-leak-in-issue-1054.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,44 @@
+From: Yun <emptyiscolor at gmail.com>
+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.9.14+dfsg/debian/patches/0038-schematron-fix-additional-memory-leaks-on-error-path.patch libxml2-2.9.14+dfsg/debian/patches/0038-schematron-fix-additional-memory-leaks-on-error-path.patch
--- libxml2-2.9.14+dfsg/debian/patches/0038-schematron-fix-additional-memory-leaks-on-error-path.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/0038-schematron-fix-additional-memory-leaks-on-error-path.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,51 @@
+From: ylwango613 <1217816127 at 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 5782636..ab4a4ea 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.9.14+dfsg/debian/patches/0039-catalog-fix-stack-overflow-from-self-referencing-SGM.patch libxml2-2.9.14+dfsg/debian/patches/0039-catalog-fix-stack-overflow-from-self-referencing-SGM.patch
--- libxml2-2.9.14+dfsg/debian/patches/0039-catalog-fix-stack-overflow-from-self-referencing-SGM.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/0039-catalog-fix-stack-overflow-from-self-referencing-SGM.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,45 @@
+From: ylwango613 <1217816127 at 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.9.14+dfsg/debian/patches/CVE-2025-49794_CVE-2025-49796.patch libxml2-2.9.14+dfsg/debian/patches/CVE-2025-49794_CVE-2025-49796.patch
--- libxml2-2.9.14+dfsg/debian/patches/CVE-2025-49794_CVE-2025-49796.patch	2025-10-11 14:41:17.000000000 +0200
+++ libxml2-2.9.14+dfsg/debian/patches/CVE-2025-49794_CVE-2025-49796.patch	2026-06-07 17:53:53.000000000 +0200
@@ -13,21 +13,38 @@
 Bug-Debian: https://bugs.debian.org/1107752
 Bug-Debian: https://bugs.debian.org/1107755
 ---
+ result/schematron/cve-2025-49794_0     |  7 +++++
  result/schematron/cve-2025-49794_0.err |  3 ++
+ result/schematron/cve-2025-49796_0     |  4 +++
  result/schematron/cve-2025-49796_0.err |  3 ++
  schematron.c                           | 54 ++++++++++++++++++----------------
  test/schematron/cve-2025-49794.sct     | 10 +++++++
  test/schematron/cve-2025-49794_0.xml   |  6 ++++
  test/schematron/cve-2025-49796.sct     |  9 ++++++
  test/schematron/cve-2025-49796_0.xml   |  3 ++
- 7 files changed, 63 insertions(+), 25 deletions(-)
+ 9 files changed, 74 insertions(+), 25 deletions(-)
+ create mode 100644 result/schematron/cve-2025-49794_0
  create mode 100644 result/schematron/cve-2025-49794_0.err
+ create mode 100644 result/schematron/cve-2025-49796_0
  create mode 100644 result/schematron/cve-2025-49796_0.err
  create mode 100644 test/schematron/cve-2025-49794.sct
  create mode 100644 test/schematron/cve-2025-49794_0.xml
  create mode 100644 test/schematron/cve-2025-49796.sct
  create mode 100644 test/schematron/cve-2025-49796_0.xml
 
+diff --git a/result/schematron/cve-2025-49794_0 b/result/schematron/cve-2025-49794_0
+new file mode 100644
+index 0000000..55199ec
+--- /dev/null
++++ b/result/schematron/cve-2025-49794_0
+@@ -0,0 +1,7 @@
++<?xml version="1.0"?>
++<librar0>
++    <boo0 t="">
++        <author/>
++    </boo0>
++    <ins/>
++</librar0>
 diff --git a/result/schematron/cve-2025-49794_0.err b/result/schematron/cve-2025-49794_0.err
 new file mode 100644
 index 0000000..618ae11
@@ -37,6 +54,16 @@
 +Pattern: 
 +/librar0/boo0 line 2:  
 +./test/schematron/cve-2025-49794_0.xml fails to validate
+diff --git a/result/schematron/cve-2025-49796_0 b/result/schematron/cve-2025-49796_0
+new file mode 100644
+index 0000000..54e9020
+--- /dev/null
++++ b/result/schematron/cve-2025-49796_0
+@@ -0,0 +1,4 @@
++<?xml version="1.0"?>
++<librar0>
++    <boo0/>
++</librar0>
 diff --git a/result/schematron/cve-2025-49796_0.err b/result/schematron/cve-2025-49796_0.err
 new file mode 100644
 index 0000000..0d0146b
diff -Nru libxml2-2.9.14+dfsg/debian/patches/CVE-2025-8732.patch libxml2-2.9.14+dfsg/debian/patches/CVE-2025-8732.patch
--- libxml2-2.9.14+dfsg/debian/patches/CVE-2025-8732.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/CVE-2025-8732.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,149 @@
+From: Nathan <nathan.shain at echohq.com>
+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.9.14+dfsg/debian/patches/CVE-2026-0989.patch libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0989.patch
--- libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0989.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0989.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,308 @@
+From: Daniel Garcia Moreno <daniel.garcia at suse.com>
+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 <errno.h>
++#include <stdlib.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <stddef.h>
+@@ -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 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++    <include href="include-limit_1.rng"/>
++</grammar>
+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 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++    <include href="include-limit_2.rng"/>
++</grammar>
+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 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++    <include href="include-limit_3.rng"/>
++</grammar>
+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 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++    <start>
++        <element name="root">
++            <empty/>
++        </element>
++    </start>
++</grammar>
diff -Nru libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0990.patch libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0990.patch
--- libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0990.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0990.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,74 @@
+From: Daniel Garcia Moreno <daniel.garcia at suse.com>
+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.9.14+dfsg/debian/patches/CVE-2026-0992/01-4af23b523.patch libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0992/01-4af23b523.patch
--- libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0992/01-4af23b523.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0992/01-4af23b523.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,47 @@
+From: Daniel Garcia Moreno <daniel.garcia at suse.com>
+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.9.14+dfsg/debian/patches/CVE-2026-0992/02-096402c94.patch libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0992/02-096402c94.patch
--- libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0992/02-096402c94.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/CVE-2026-0992/02-096402c94.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,31 @@
+From: Daniel Garcia Moreno <dani at danigm.net>
+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.9.14+dfsg/debian/patches/CVE-2026-1757.patch libxml2-2.9.14+dfsg/debian/patches/CVE-2026-1757.patch
--- libxml2-2.9.14+dfsg/debian/patches/CVE-2026-1757.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/CVE-2026-1757.patch	2026-06-07 17:53:53.000000000 +0200
@@ -0,0 +1,34 @@
+From: Daniel Garcia Moreno <daniel.garcia at suse.com>
+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.9.14+dfsg/debian/patches/series libxml2-2.9.14+dfsg/debian/patches/series
--- libxml2-2.9.14+dfsg/debian/patches/series	2025-10-11 14:41:17.000000000 +0200
+++ libxml2-2.9.14+dfsg/debian/patches/series	2026-06-07 17:53:53.000000000 +0200
@@ -25,3 +25,15 @@
 CVE-2025-49794_CVE-2025-49796.patch
 CVE-2025-7425.patch
 CVE-2025-9714.patch
+CVE-2026-1757.patch
+0029-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
+0034-testcatalog-Add-new-tests-for-catalog.c.patch
+CVE-2026-0989.patch
+0036-use-duplicating-variant-in-relaxng-to-mitigate-UAF.patch
+0037-fix-memory-leak-in-issue-1054.patch
+0038-schematron-fix-additional-memory-leaks-on-error-path.patch
+0039-catalog-fix-stack-overflow-from-self-referencing-SGM.patch
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://alioth-lists.debian.net/pipermail/debian-xml-sgml-pkgs/attachments/20260607/fbc6e3cf/attachment-0001.sig>


More information about the debian-xml-sgml-pkgs mailing list