[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1117844: bookworm-pu: package libxml2/2.9.14+dfsg-1.3~deb12u5



Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: libxml2.9@packages.debian.org, security@debian.org
Control: affects -1 + src:libxml2.9
User: release.debian.org@packages.debian.org
Usertags: pu

[ Reason ]

Fix <no-dsa> issue CVE-2025-9714 and improve existing mitigation for
CVE-2025-7425.

[ Impact ]

Users will remain vulnerable to CVE-2025-9714, and will regress when
upgrading (a fix was uploaded to Bullseye LTS).

[ Tests ]

1/ PoC (from libxslt) at https://gitlab.gnome.org/GNOME/libxslt/-/issues/140
and https://gitlab.gnome.org/GNOME/libxslt/-/issues/148 .

2/ Autopkgtests for reverse (build-)dependencies.

[ Risks ]

The upstream fix for CVE-2025-9714 trivially applies to
2.9.14+dfsg-1.3~deb12u4.

Backporting the mitigation for CVE-2025-7425 from
https://gitlab.gnome.org/-/project/1762/uploads/302ecfda701895ebd0fa438a66d1a7a4/gnome-libxslt-bug-140-apple-fix.diff
was more involved.  Improvements over the existing
d/p/CVE-2025-7425.patch were discussed offlist with Aron Xu; a version
containing the resulting patch was uploaded to Bullseye LTS.

[ Checklist ]

  [*] *all* changes are documented in the d/changelog
  [*] I reviewed all changes and I approve them
  [*] attach debdiff against the package in oldstable
  [*] the issue is verified as fixed in unstable

[ Changes ]

  * Fix CVE-2025-9714: Denial of service vulnerability via uncontrolled
    recursion in XPath evaluation.
  * Amend d/p/CVE-2025-7425.patch to better reflect the original fix.

-- 
Guilhem.
diffstat for libxml2-2.9.14+dfsg libxml2-2.9.14+dfsg

 changelog                   |    9 
 patches/CVE-2025-7425.patch |  441 +++++++++++++++-----------------------------
 patches/CVE-2025-9714.patch |  113 +++++++++++
 patches/series              |    1 
 4 files changed, 277 insertions(+), 287 deletions(-)

diff -Nru libxml2-2.9.14+dfsg/debian/changelog libxml2-2.9.14+dfsg/debian/changelog
--- libxml2-2.9.14+dfsg/debian/changelog	2025-08-25 13:30:10.000000000 +0200
+++ libxml2-2.9.14+dfsg/debian/changelog	2025-10-11 14:41:17.000000000 +0200
@@ -1,3 +1,12 @@
+libxml2 (2.9.14+dfsg-1.3~deb12u5) bookworm; urgency=high
+
+  * Non-maintainer upload.
+  * Fix CVE-2025-9714: Denial of service vulnerability via uncontrolled
+    recursion in XPath evaluation.
+  * Amend d/p/CVE-2025-7425.patch to better reflect the original fix.
+
+ -- Guilhem Moulin <guilhem@debian.org>  Sat, 11 Oct 2025 14:41:17 +0200
+
 libxml2 (2.9.14+dfsg-1.3~deb12u4) bookworm-security; urgency=high
 
   * CVE-2025-7425: heap-use-after-free in xmlFreeID caused by `atype`
diff -Nru libxml2-2.9.14+dfsg/debian/patches/CVE-2025-7425.patch libxml2-2.9.14+dfsg/debian/patches/CVE-2025-7425.patch
--- libxml2-2.9.14+dfsg/debian/patches/CVE-2025-7425.patch	2025-08-25 13:29:44.000000000 +0200
+++ libxml2-2.9.14+dfsg/debian/patches/CVE-2025-7425.patch	2025-10-11 14:41:17.000000000 +0200
@@ -59,35 +59,42 @@
 (xmlSchemaValAtomicType):
 - Adopt macros by renaming the struct fields, recompiling and fixing
   compiler failures, then changing the struct field names back.
+
+Origin: https://gitlab.gnome.org/-/project/1762/uploads/302ecfda701895ebd0fa438a66d1a7a4/gnome-libxslt-bug-140-apple-fix.diff
+Bug: https://gitlab.gnome.org/GNOME/libxslt/-/issues/140
+Bug: https://bugzilla.redhat.com/show_bug.cgi?id=2379274
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2025-7425
+Bug-Debian: https://bugs.debian.org/1109122
 ---
- HTMLparser.c          |  1 +
- SAX2.c                |  6 ++--
- include/libxml/tree.h | 14 ++++++++-
- parser.c              |  8 ++---
- runxmlconf.c          |  4 +--
- tree.c                | 20 ++++++-------
- valid.c               | 68 +++++++++++++++++++++----------------------
- xmlreader.c           | 30 +++++++++----------
- xmlschemas.c          |  4 +--
- xmlschemastypes.c     | 12 ++++----
- 10 files changed, 90 insertions(+), 77 deletions(-)
+ HTMLparser.c          |  2 +-
+ SAX2.c                |  6 +++---
+ include/libxml/tree.h | 14 +++++++++++++-
+ parser.c              | 26 +++++++++++++-------------
+ runxmlconf.c          |  4 ++--
+ tree.c                | 20 ++++++++++----------
+ valid.c               | 16 ++++++++--------
+ xmlreader.c           | 30 +++++++++++++++---------------
+ xmlschemas.c          |  4 ++--
+ xmlschemastypes.c     | 12 ++++++------
+ 10 files changed, 73 insertions(+), 61 deletions(-)
 
-Index: libxml2-2.9.14+dfsg/HTMLparser.c
-===================================================================
---- libxml2-2.9.14+dfsg.orig/HTMLparser.c
-+++ libxml2-2.9.14+dfsg/HTMLparser.c
-@@ -2514,6 +2514,7 @@ htmlNewDocNoDtD(const xmlChar *URI, cons
+diff --git a/HTMLparser.c b/HTMLparser.c
+index 4a56fb1..eabca3a 100644
+--- a/HTMLparser.c
++++ b/HTMLparser.c
+@@ -2514,7 +2514,7 @@ htmlNewDocNoDtD(const xmlChar *URI, const xmlChar *ExternalID) {
      cur->refs = NULL;
      cur->_private = NULL;
      cur->charset = XML_CHAR_ENCODING_UTF8;
+-    cur->properties = XML_DOC_HTML | XML_DOC_USERBUILT;
 +    XML_DOC_SET_PROPERTIES(cur, XML_DOC_HTML | XML_DOC_USERBUILT);
-     cur->properties = XML_DOC_HTML | XML_DOC_USERBUILT;
      if ((ExternalID != NULL) ||
  	(URI != NULL))
-Index: libxml2-2.9.14+dfsg/SAX2.c
-===================================================================
---- libxml2-2.9.14+dfsg.orig/SAX2.c
-+++ libxml2-2.9.14+dfsg/SAX2.c
+ 	xmlCreateIntSubset(cur, BAD_CAST "html", ExternalID, URI);
+diff --git a/SAX2.c b/SAX2.c
+index f7c77c2..0d8e84a 100644
+--- a/SAX2.c
++++ b/SAX2.c
 @@ -970,7 +970,7 @@ xmlSAX2StartDocument(void *ctx)
  	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
  	    return;
@@ -109,10 +116,10 @@
  	    doc->parseFlags = ctxt->options;
  	    if (ctxt->encoding != NULL)
  		doc->encoding = xmlStrdup(ctxt->encoding);
-Index: libxml2-2.9.14+dfsg/include/libxml/tree.h
-===================================================================
---- libxml2-2.9.14+dfsg.orig/include/libxml/tree.h
-+++ libxml2-2.9.14+dfsg/include/libxml/tree.h
+diff --git a/include/libxml/tree.h b/include/libxml/tree.h
+index 1e79be9..61178b2 100644
+--- a/include/libxml/tree.h
++++ b/include/libxml/tree.h
 @@ -365,7 +365,6 @@ struct _xmlElement {
  #endif
  };
@@ -155,11 +162,11 @@
  
  typedef struct _xmlDOMWrapCtxt xmlDOMWrapCtxt;
  typedef xmlDOMWrapCtxt *xmlDOMWrapCtxtPtr;
-Index: libxml2-2.9.14+dfsg/parser.c
-===================================================================
---- libxml2-2.9.14+dfsg.orig/parser.c
-+++ libxml2-2.9.14+dfsg/parser.c
-@@ -5523,7 +5523,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt
+diff --git a/parser.c b/parser.c
+index 603c0b3..f859296 100644
+--- a/parser.c
++++ b/parser.c
+@@ -5523,7 +5523,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
  			    xmlErrMemory(ctxt, "New Doc failed");
  			    return;
  			}
@@ -168,7 +175,7 @@
  		    }
  		    if (ctxt->myDoc->intSubset == NULL)
  			ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
-@@ -5594,7 +5594,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt
+@@ -5594,7 +5594,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
  			        xmlErrMemory(ctxt, "New Doc failed");
  				return;
  			    }
@@ -177,7 +184,7 @@
  			}
  
  			if (ctxt->myDoc->intSubset == NULL)
-@@ -7035,7 +7035,7 @@ xmlParseExternalSubset(xmlParserCtxtPtr
+@@ -7035,7 +7035,7 @@ xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
  	    xmlErrMemory(ctxt, "New Doc failed");
  	    return;
  	}
@@ -186,7 +193,7 @@
      }
      if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
          xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
-@@ -7419,7 +7419,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt)
+@@ -7419,7 +7419,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
  			    (nw != NULL) &&
  			    (nw->type == XML_ELEMENT_NODE) &&
  			    (nw->children == NULL))
@@ -195,11 +202,74 @@
  
  			break;
  		    }
-Index: libxml2-2.9.14+dfsg/runxmlconf.c
-===================================================================
---- libxml2-2.9.14+dfsg.orig/runxmlconf.c
-+++ libxml2-2.9.14+dfsg/runxmlconf.c
-@@ -197,7 +197,7 @@ xmlconfTestInvalid(const char *id, const
+@@ -10858,13 +10858,13 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
+     }
+ 
+     if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
+-        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
++        XML_DOC_ADD_PROPERTIES(ctxt->myDoc, XML_DOC_WELLFORMED);
+ 	if (ctxt->valid)
+-	    ctxt->myDoc->properties |= XML_DOC_DTDVALID;
++	    XML_DOC_ADD_PROPERTIES(ctxt->myDoc, XML_DOC_DTDVALID);
+ 	if (ctxt->nsWellFormed)
+-	    ctxt->myDoc->properties |= XML_DOC_NSVALID;
++	    XML_DOC_ADD_PROPERTIES(ctxt->myDoc, XML_DOC_NSVALID);
+ 	if (ctxt->options & XML_PARSE_OLD10)
+-	    ctxt->myDoc->properties |= XML_DOC_OLD10;
++	    XML_DOC_ADD_PROPERTIES(ctxt->myDoc, XML_DOC_OLD10);
+     }
+     if (! ctxt->wellFormed) {
+ 	ctxt->valid = 0;
+@@ -12748,7 +12748,7 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
+ 	xmlErrMemory(ctxt, "New Doc failed");
+ 	return(NULL);
+     }
+-    ctxt->myDoc->properties = XML_DOC_INTERNAL;
++    XML_DOC_SET_PROPERTIES(ctxt->myDoc, XML_DOC_INTERNAL);
+     ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
+ 	                               BAD_CAST "none", BAD_CAST "none");
+ 
+@@ -12897,7 +12897,7 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
+ 	xmlFreeParserCtxt(ctxt);
+ 	return(NULL);
+     }
+-    ctxt->myDoc->properties = XML_DOC_INTERNAL;
++    XML_DOC_SET_PROPERTIES(ctxt->myDoc, XML_DOC_INTERNAL);
+     ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
+ 	                               ExternalID, SystemID);
+     xmlParseExternalSubset(ctxt, ExternalID, SystemID);
+@@ -13047,7 +13047,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
+ 	xmlFreeParserCtxt(ctxt);
+ 	return(XML_ERR_INTERNAL_ERROR);
+     }
+-    newDoc->properties = XML_DOC_INTERNAL;
++    XML_DOC_SET_PROPERTIES(newDoc, XML_DOC_INTERNAL);
+     if (doc) {
+         newDoc->intSubset = doc->intSubset;
+         newDoc->extSubset = doc->extSubset;
+@@ -13366,7 +13366,7 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
+ 	    xmlFreeParserCtxt(ctxt);
+ 	    return(XML_ERR_INTERNAL_ERROR);
+ 	}
+-	newDoc->properties = XML_DOC_INTERNAL;
++	XML_DOC_SET_PROPERTIES(newDoc, XML_DOC_INTERNAL);
+ 	newDoc->dict = ctxt->dict;
+ 	xmlDictReference(newDoc->dict);
+ 	ctxt->myDoc = newDoc;
+@@ -13768,7 +13768,7 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
+ 	xmlFreeParserCtxt(ctxt);
+ 	return(-1);
+     }
+-    newDoc->properties = XML_DOC_INTERNAL;
++    XML_DOC_SET_PROPERTIES(newDoc, XML_DOC_INTERNAL);
+     if ((doc != NULL) && (doc->dict != NULL)) {
+         xmlDictFree(ctxt->dict);
+ 	ctxt->dict = doc->dict;
+diff --git a/runxmlconf.c b/runxmlconf.c
+index 8a37aa8..601a0af 100644
+--- a/runxmlconf.c
++++ b/runxmlconf.c
+@@ -197,7 +197,7 @@ xmlconfTestInvalid(const char *id, const char *filename, int options) {
  	         id, filename);
      } else {
      /* invalidity should be reported both in the context and in the document */
@@ -208,7 +278,7 @@
  	    test_log("test %s : %s failed to detect invalid document\n",
  		     id, filename);
  	    nb_errors++;
-@@ -229,7 +229,7 @@ xmlconfTestValid(const char *id, const c
+@@ -229,7 +229,7 @@ xmlconfTestValid(const char *id, const char *filename, int options) {
  	ret = 0;
      } else {
      /* validity should be reported both in the context and in the document */
@@ -217,10 +287,10 @@
  	    test_log("test %s : %s failed to validate a valid document\n",
  		     id, filename);
  	    nb_errors++;
-Index: libxml2-2.9.14+dfsg/tree.c
-===================================================================
---- libxml2-2.9.14+dfsg.orig/tree.c
-+++ libxml2-2.9.14+dfsg/tree.c
+diff --git a/tree.c b/tree.c
+index 60cc6f4..2ce9f7e 100644
+--- a/tree.c
++++ b/tree.c
 @@ -1192,7 +1192,7 @@ xmlNewDoc(const xmlChar *version) {
      cur->compression = -1; /* not initialized */
      cur->doc = cur;
@@ -239,7 +309,7 @@
  	    xmlRemoveID(cur->doc, cur);
      }
      if (cur->children != NULL) xmlFreeNodeList(cur->children);
-@@ -2838,7 +2838,7 @@ xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr
+@@ -2838,7 +2838,7 @@ xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
  	if(tree->type == XML_ELEMENT_NODE) {
  	    prop = tree->properties;
  	    while (prop != NULL) {
@@ -248,7 +318,7 @@
                      xmlRemoveID(tree->doc, prop);
                  }
  
-@@ -6952,9 +6952,9 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr n
+@@ -6952,9 +6952,9 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
  	/*
  	* Modify the attribute's value.
  	*/
@@ -260,7 +330,7 @@
  	}
  	if (prop->children != NULL)
  	    xmlFreeNodeList(prop->children);
-@@ -6974,7 +6974,7 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr n
+@@ -6974,7 +6974,7 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
  		tmp = tmp->next;
  	    }
  	}
@@ -292,7 +362,7 @@
  		    ((xmlAttrPtr) cur)->psvi = NULL;
  		}
  		break;
-@@ -9991,7 +9991,7 @@ xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ct
+@@ -9991,7 +9991,7 @@ xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt,
      }
  
      XML_TREE_ADOPT_STR(attr->name);
@@ -301,20 +371,11 @@
      attr->psvi = NULL;
      /*
      * Walk content.
-Index: libxml2-2.9.14+dfsg/valid.c
-===================================================================
---- libxml2-2.9.14+dfsg.orig/valid.c
-+++ libxml2-2.9.14+dfsg/valid.c
-@@ -1906,7 +1906,7 @@ xmlScanIDAttributeDecl(xmlValidCtxtPtr c
-     if (elem == NULL) return(0);
-     cur = elem->attributes;
-     while (cur != NULL) {
--        if (cur->atype == XML_ATTRIBUTE_ID) {
-+        if (XML_ATTR_GET_ATYPE(cur) == XML_ATTRIBUTE_ID) {
- 	    ret ++;
- 	    if ((ret > 1) && (err))
- 		xmlErrValidNode(ctxt, (xmlNodePtr) elem, XML_DTD_MULTIPLE_ID,
-@@ -2279,7 +2279,7 @@ xmlDumpAttributeDecl(xmlBufferPtr buf, x
+diff --git a/valid.c b/valid.c
+index 36a0435..28822a2 100644
+--- a/valid.c
++++ b/valid.c
+@@ -2279,7 +2279,7 @@ xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
  	xmlBufferWriteChar(buf, ":");
      }
      xmlBufferWriteCHAR(buf, attr->name);
@@ -323,7 +384,7 @@
  	case XML_ATTRIBUTE_CDATA:
  	    xmlBufferWriteChar(buf, " CDATA");
  	    break;
-@@ -2758,7 +2758,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr
+@@ -2758,7 +2758,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
  	return(NULL);
      }
      if (attr != NULL)
@@ -332,16 +393,7 @@
      return(ret);
  }
  
-@@ -2837,7 +2837,7 @@ xmlIsID(xmlDocPtr doc, xmlNodePtr elem,
- 	if ((fullelemname != felem) && (fullelemname != elem->name))
- 	    xmlFree(fullelemname);
- 
--        if ((attrDecl != NULL) && (attrDecl->atype == XML_ATTRIBUTE_ID))
-+        if ((attrDecl != NULL) && (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_ID))
- 	    return(1);
-     }
-     return(0);
-@@ -2878,7 +2878,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr at
+@@ -2878,7 +2878,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
  
      xmlHashRemoveEntry(table, ID, xmlFreeIDTableEntry);
      xmlFree(ID);
@@ -350,18 +402,7 @@
      return(0);
  }
  
-@@ -3157,8 +3157,8 @@ xmlIsRef(xmlDocPtr doc, xmlNodePtr elem,
- 		                         elem->name, attr->name);
- 
- 	if ((attrDecl != NULL) &&
--	    (attrDecl->atype == XML_ATTRIBUTE_IDREF ||
--	     attrDecl->atype == XML_ATTRIBUTE_IDREFS))
-+	    (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_IDREF ||
-+	     XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_IDREFS))
- 	return(1);
-     }
-     return(0);
-@@ -3532,7 +3532,7 @@ xmlIsMixedElement(xmlDocPtr doc, const x
+@@ -3532,7 +3532,7 @@ xmlIsMixedElement(xmlDocPtr doc, const xmlChar *name) {
  
  static int
  xmlIsDocNameStartChar(xmlDocPtr doc, int c) {
@@ -370,7 +411,7 @@
          /*
  	 * Use the new checks of production [4] [4a] amd [5] of the
  	 * Update 5 of XML-1.0
-@@ -3562,7 +3562,7 @@ xmlIsDocNameStartChar(xmlDocPtr doc, int
+@@ -3562,7 +3562,7 @@ xmlIsDocNameStartChar(xmlDocPtr doc, int c) {
  
  static int
  xmlIsDocNameChar(xmlDocPtr doc, int c) {
@@ -379,155 +420,16 @@
          /*
  	 * Use the new checks of production [4] [4a] amd [5] of the
  	 * Update 5 of XML-1.0
-@@ -4112,7 +4112,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlV
- 
-     if (attrDecl == NULL)
- 	return(NULL);
--    if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
-+    if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_CDATA)
- 	return(NULL);
- 
-     ret = xmlStrdup(value);
-@@ -4174,7 +4174,7 @@ xmlValidNormalizeAttributeValue(xmlDocPt
- 
-     if (attrDecl == NULL)
- 	return(NULL);
--    if (attrDecl->atype == XML_ATTRIBUTE_CDATA)
-+    if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_CDATA)
- 	return(NULL);
- 
-     ret = xmlStrdup(value);
-@@ -4189,7 +4189,7 @@ xmlValidateAttributeIdCallback(void *pay
- 	                       const xmlChar *name ATTRIBUTE_UNUSED) {
-     xmlAttributePtr attr = (xmlAttributePtr) payload;
-     int *count = (int *) data;
--    if (attr->atype == XML_ATTRIBUTE_ID) (*count)++;
-+    if (XML_ATTR_GET_ATYPE(attr) == XML_ATTRIBUTE_ID) (*count)++;
- }
- 
- /**
-@@ -4221,7 +4221,7 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr
-     /* Attribute Default Legal */
-     /* Enumeration */
-     if (attr->defaultValue != NULL) {
--	val = xmlValidateAttributeValueInternal(doc, attr->atype,
-+	val = xmlValidateAttributeValueInternal(doc, XML_ATTR_GET_ATYPE(attr),
- 	                                        attr->defaultValue);
- 	if (val == 0) {
- 	    xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ATTRIBUTE_DEFAULT,
-@@ -4232,7 +4232,7 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr
-     }
- 
-     /* ID Attribute Default */
--    if ((attr->atype == XML_ATTRIBUTE_ID)&&
-+    if ((XML_ATTR_GET_ATYPE(attr) == XML_ATTRIBUTE_ID)&&
-         (attr->def != XML_ATTRIBUTE_IMPLIED) &&
- 	(attr->def != XML_ATTRIBUTE_REQUIRED)) {
- 	xmlErrValidNode(ctxt, (xmlNodePtr) attr, XML_DTD_ID_FIXED,
-@@ -4242,7 +4242,7 @@ xmlValidateAttributeDecl(xmlValidCtxtPtr
-     }
- 
-     /* One ID per Element Type */
--    if (attr->atype == XML_ATTRIBUTE_ID) {
-+    if (XML_ATTR_GET_ATYPE(attr) == XML_ATTRIBUTE_ID) {
-         int nbId;
- 
- 	/* the trick is that we parse DtD as their own internal subset */
-@@ -4501,9 +4501,9 @@ xmlValidateOneAttribute(xmlValidCtxtPtr
+@@ -4501,7 +4501,7 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
  	       attr->name, elem->name, NULL);
  	return(0);
      }
 -    attr->atype = attrDecl->atype;
 +    XML_ATTR_SET_ATYPE(attr, attrDecl->atype);
  
--    val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
-+    val = xmlValidateAttributeValueInternal(doc, XML_ATTR_GET_ATYPE(attrDecl), value);
+     val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
      if (val == 0) {
- 	    xmlErrValidNode(ctxt, elem, XML_DTD_ATTRIBUTE_VALUE,
- 	   "Syntax of value for attribute %s of %s is not valid\n",
-@@ -4522,19 +4522,19 @@ xmlValidateOneAttribute(xmlValidCtxtPtr
-     }
- 
-     /* Validity Constraint: ID uniqueness */
--    if (attrDecl->atype == XML_ATTRIBUTE_ID) {
-+    if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_ID) {
-         if (xmlAddID(ctxt, doc, value, attr) == NULL)
- 	    ret = 0;
-     }
- 
--    if ((attrDecl->atype == XML_ATTRIBUTE_IDREF) ||
--	(attrDecl->atype == XML_ATTRIBUTE_IDREFS)) {
-+    if ((XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_IDREF) ||
-+	(XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_IDREFS)) {
-         if (xmlAddRef(ctxt, doc, value, attr) == NULL)
- 	    ret = 0;
-     }
- 
-     /* Validity Constraint: Notation Attributes */
--    if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
-+    if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_NOTATION) {
-         xmlEnumerationPtr tree = attrDecl->tree;
-         xmlNotationPtr nota;
- 
-@@ -4564,7 +4564,7 @@ xmlValidateOneAttribute(xmlValidCtxtPtr
-     }
- 
-     /* Validity Constraint: Enumeration */
--    if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
-+    if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_ENUMERATION) {
-         xmlEnumerationPtr tree = attrDecl->tree;
- 	while (tree != NULL) {
- 	    if (xmlStrEqual(tree->name, value)) break;
-@@ -4589,7 +4589,7 @@ xmlValidateOneAttribute(xmlValidCtxtPtr
- 
-     /* Extra check for the attribute value */
-     ret &= xmlValidateAttributeValue2(ctxt, doc, attr->name,
--				      attrDecl->atype, value);
-+				      XML_ATTR_GET_ATYPE(attrDecl), value);
- 
-     return(ret);
- }
-@@ -4688,7 +4688,7 @@ xmlNodePtr elem, const xmlChar *prefix,
- 	return(0);
-     }
- 
--    val = xmlValidateAttributeValueInternal(doc, attrDecl->atype, value);
-+    val = xmlValidateAttributeValueInternal(doc, XML_ATTR_GET_ATYPE(attrDecl), value);
-     if (val == 0) {
- 	if (ns->prefix != NULL) {
- 	    xmlErrValidNode(ctxt, elem, XML_DTD_INVALID_DEFAULT,
-@@ -4738,7 +4738,7 @@ xmlNodePtr elem, const xmlChar *prefix,
- #endif
- 
-     /* Validity Constraint: Notation Attributes */
--    if (attrDecl->atype == XML_ATTRIBUTE_NOTATION) {
-+    if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_NOTATION) {
-         xmlEnumerationPtr tree = attrDecl->tree;
-         xmlNotationPtr nota;
- 
-@@ -4780,7 +4780,7 @@ xmlNodePtr elem, const xmlChar *prefix,
-     }
- 
-     /* Validity Constraint: Enumeration */
--    if (attrDecl->atype == XML_ATTRIBUTE_ENUMERATION) {
-+    if (XML_ATTR_GET_ATYPE(attrDecl) == XML_ATTRIBUTE_ENUMERATION) {
-         xmlEnumerationPtr tree = attrDecl->tree;
- 	while (tree != NULL) {
- 	    if (xmlStrEqual(tree->name, value)) break;
-@@ -4818,10 +4818,10 @@ xmlNodePtr elem, const xmlChar *prefix,
-     /* Extra check for the attribute value */
-     if (ns->prefix != NULL) {
- 	ret &= xmlValidateAttributeValue2(ctxt, doc, ns->prefix,
--					  attrDecl->atype, value);
-+					  XML_ATTR_GET_ATYPE(attrDecl), value);
-     } else {
- 	ret &= xmlValidateAttributeValue2(ctxt, doc, BAD_CAST "xmlns",
--					  attrDecl->atype, value);
-+					  XML_ATTR_GET_ATYPE(attrDecl), value);
-     }
- 
-     return(ret);
-@@ -6574,7 +6574,7 @@ xmlValidateRef(xmlRefPtr ref, xmlValidCt
+@@ -6574,7 +6574,7 @@ xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
  	    while (IS_BLANK_CH(*cur)) cur++;
  	}
  	xmlFree(dup);
@@ -536,7 +438,7 @@
  	id = xmlGetID(ctxt->doc, name);
  	if (id == NULL) {
  	    xmlErrValidNode(ctxt, attr->parent, XML_DTD_UNKNOWN_ID,
-@@ -6582,7 +6582,7 @@ xmlValidateRef(xmlRefPtr ref, xmlValidCt
+@@ -6582,7 +6582,7 @@ xmlValidateRef(xmlRefPtr ref, xmlValidCtxtPtr ctxt,
  		   attr->name, name, NULL);
  	    ctxt->valid = 0;
  	}
@@ -545,46 +447,11 @@
  	xmlChar *dup, *str = NULL, *cur, save;
  
  	dup = xmlStrdup(name);
-@@ -6782,7 +6782,7 @@ xmlValidateAttributeCallback(void *paylo
- 
-     if (cur == NULL)
- 	return;
--    switch (cur->atype) {
-+    switch (XML_ATTR_GET_ATYPE(cur)) {
- 	case XML_ATTRIBUTE_CDATA:
- 	case XML_ATTRIBUTE_ID:
- 	case XML_ATTRIBUTE_IDREF	:
-@@ -6797,7 +6797,7 @@ xmlValidateAttributeCallback(void *paylo
- 	    if (cur->defaultValue != NULL) {
- 
- 		ret = xmlValidateAttributeValue2(ctxt, ctxt->doc, cur->name,
--			                         cur->atype, cur->defaultValue);
-+			                         XML_ATTR_GET_ATYPE(cur), cur->defaultValue);
- 		if ((ret == 0) && (ctxt->valid == 1))
- 		    ctxt->valid = 0;
- 	    }
-@@ -6805,14 +6805,14 @@ xmlValidateAttributeCallback(void *paylo
- 		xmlEnumerationPtr tree = cur->tree;
- 		while (tree != NULL) {
- 		    ret = xmlValidateAttributeValue2(ctxt, ctxt->doc,
--				    cur->name, cur->atype, tree->name);
-+				    cur->name, XML_ATTR_GET_ATYPE(cur), tree->name);
- 		    if ((ret == 0) && (ctxt->valid == 1))
- 			ctxt->valid = 0;
- 		    tree = tree->next;
- 		}
- 	    }
-     }
--    if (cur->atype == XML_ATTRIBUTE_NOTATION) {
-+    if (XML_ATTR_GET_ATYPE(cur) == XML_ATTRIBUTE_NOTATION) {
- 	doc = cur->doc;
- 	if (cur->elem == NULL) {
- 	    xmlErrValid(ctxt, XML_ERR_INTERNAL_ERROR,
-Index: libxml2-2.9.14+dfsg/xmlreader.c
-===================================================================
---- libxml2-2.9.14+dfsg.orig/xmlreader.c
-+++ libxml2-2.9.14+dfsg/xmlreader.c
-@@ -753,7 +753,7 @@ xmlTextReaderStartElement(void *ctx, con
+diff --git a/xmlreader.c b/xmlreader.c
+index 67ff2cd..2a1a66a 100644
+--- a/xmlreader.c
++++ b/xmlreader.c
+@@ -753,7 +753,7 @@ xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
  	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
  	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
  	    (ctxt->input->cur[1] == '>'))
@@ -674,7 +541,7 @@
  	xmlNodePtr tmp = reader->node->last;
  	xmlUnlinkNode(tmp);
  	xmlTextReaderFreeNode(reader, tmp);
-@@ -1741,7 +1741,7 @@ xmlTextReaderNext(xmlTextReaderPtr reade
+@@ -1741,7 +1741,7 @@ xmlTextReaderNext(xmlTextReaderPtr reader) {
          return(xmlTextReaderRead(reader));
      if (reader->state == XML_TEXTREADER_END || reader->state == XML_TEXTREADER_BACKTRACK)
          return(xmlTextReaderRead(reader));
@@ -683,7 +550,7 @@
          return(xmlTextReaderRead(reader));
      do {
          ret = xmlTextReaderRead(reader);
-@@ -3167,7 +3167,7 @@ xmlTextReaderIsEmptyElement(xmlTextReade
+@@ -3167,7 +3167,7 @@ xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader) {
      if (reader->in_xinclude > 0)
          return(1);
  #endif
@@ -692,7 +559,7 @@
  }
  
  /**
-@@ -4035,15 +4035,15 @@ xmlTextReaderPreserve(xmlTextReaderPtr r
+@@ -4035,15 +4035,15 @@ xmlTextReaderPreserve(xmlTextReaderPtr reader) {
          return(NULL);
  
      if ((cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE)) {
@@ -711,11 +578,11 @@
  	parent = parent->parent;
      }
      return(cur);
-Index: libxml2-2.9.14+dfsg/xmlschemas.c
-===================================================================
---- libxml2-2.9.14+dfsg.orig/xmlschemas.c
-+++ libxml2-2.9.14+dfsg/xmlschemas.c
-@@ -6024,7 +6024,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserC
+diff --git a/xmlschemas.c b/xmlschemas.c
+index f309572..1ae078b 100644
+--- a/xmlschemas.c
++++ b/xmlschemas.c
+@@ -6024,7 +6024,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
  	/*
  	* NOTE: the IDness might have already be declared in the DTD
  	*/
@@ -724,7 +591,7 @@
  	    xmlIDPtr res;
  	    xmlChar *strip;
  
-@@ -6047,7 +6047,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserC
+@@ -6047,7 +6047,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
  		    NULL, NULL, "Duplicate value '%s' of simple "
  		    "type 'xs:ID'", value, NULL);
  	    } else
@@ -733,11 +600,11 @@
  	}
      } else if (ret > 0) {
  	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
-Index: libxml2-2.9.14+dfsg/xmlschemastypes.c
-===================================================================
---- libxml2-2.9.14+dfsg.orig/xmlschemastypes.c
-+++ libxml2-2.9.14+dfsg/xmlschemastypes.c
-@@ -2867,7 +2867,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr
+diff --git a/xmlschemastypes.c b/xmlschemastypes.c
+index af31be5..d40da49 100644
+--- a/xmlschemastypes.c
++++ b/xmlschemastypes.c
+@@ -2867,7 +2867,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
                  /*
                   * NOTE: the IDness might have already be declared in the DTD
                   */
@@ -746,7 +613,7 @@
                      xmlIDPtr res;
                      xmlChar *strip;
  
-@@ -2880,7 +2880,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr
+@@ -2880,7 +2880,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
                      if (res == NULL) {
                          ret = 2;
                      } else {
@@ -755,7 +622,7 @@
                      }
                  }
              }
-@@ -2905,7 +2905,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr
+@@ -2905,7 +2905,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
                      xmlFree(strip);
                  } else
                      xmlAddRef(NULL, node->doc, value, attr);
@@ -764,7 +631,7 @@
              }
              goto done;
          case XML_SCHEMAS_IDREFS:
-@@ -2919,7 +2919,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr
+@@ -2919,7 +2919,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
                  (node->type == XML_ATTRIBUTE_NODE)) {
                  xmlAttrPtr attr = (xmlAttrPtr) node;
  
@@ -773,7 +640,7 @@
              }
              goto done;
          case XML_SCHEMAS_ENTITY:{
-@@ -2950,7 +2950,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr
+@@ -2950,7 +2950,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
                      (node->type == XML_ATTRIBUTE_NODE)) {
                      xmlAttrPtr attr = (xmlAttrPtr) node;
  
@@ -782,7 +649,7 @@
                  }
                  goto done;
              }
-@@ -2967,7 +2967,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr
+@@ -2967,7 +2967,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
                  (node->type == XML_ATTRIBUTE_NODE)) {
                  xmlAttrPtr attr = (xmlAttrPtr) node;
  
diff -Nru libxml2-2.9.14+dfsg/debian/patches/CVE-2025-9714.patch libxml2-2.9.14+dfsg/debian/patches/CVE-2025-9714.patch
--- libxml2-2.9.14+dfsg/debian/patches/CVE-2025-9714.patch	1970-01-01 01:00:00.000000000 +0100
+++ libxml2-2.9.14+dfsg/debian/patches/CVE-2025-9714.patch	2025-10-11 14:41:17.000000000 +0200
@@ -0,0 +1,113 @@
+From: Nick Wellnhofer <wellnhofer@aevum.de>
+Date: Thu, 28 Jul 2022 20:21:24 +0200
+Subject: Make XPath depth check work with recursive invocations
+
+EXSLT functions like dyn:map or dyn:evaluate invoke xmlXPathRunEval
+recursively. Don't set depth to zero but keep and restore the original
+value to avoid stack overflows when abusing these functions.
+
+Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/677a42645ef22b5a50741bad5facf9d8a8bc6d21
+Bug: https://bugzilla.redhat.com/show_bug.cgi?id=2392605
+Bug: https://gitlab.gnome.org/GNOME/libxslt/-/issues/148
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2025-9714
+---
+ xpath.c | 23 +++++++++++++++++------
+ 1 file changed, 17 insertions(+), 6 deletions(-)
+
+diff --git a/xpath.c b/xpath.c
+index c2d8458..028471d 100644
+--- a/xpath.c
++++ b/xpath.c
+@@ -13883,12 +13883,11 @@ static int
+ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
+ {
+     xmlXPathCompExprPtr comp;
++    int oldDepth;
+ 
+     if ((ctxt == NULL) || (ctxt->comp == NULL))
+ 	return(-1);
+ 
+-    ctxt->context->depth = 0;
+-
+     if (ctxt->valueTab == NULL) {
+ 	/* Allocate the value stack */
+ 	ctxt->valueTab = (xmlXPathObjectPtr *)
+@@ -13942,11 +13941,13 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
+ 	    "xmlXPathRunEval: last is less than zero\n");
+ 	return(-1);
+     }
++    oldDepth = ctxt->context->depth;
+     if (toBool)
+ 	return(xmlXPathCompOpEvalToBoolean(ctxt,
+ 	    &comp->steps[comp->last], 0));
+     else
+ 	xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]);
++    ctxt->context->depth = oldDepth;
+ 
+     return(0);
+ }
+@@ -14217,6 +14218,7 @@ xmlXPathCompExprPtr
+ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
+     xmlXPathParserContextPtr pctxt;
+     xmlXPathCompExprPtr comp;
++    int oldDepth = 0;
+ 
+ #ifdef XPATH_STREAMING
+     comp = xmlXPathTryStreamCompile(ctxt, str);
+@@ -14230,8 +14232,10 @@ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
+     if (pctxt == NULL)
+         return NULL;
+     if (ctxt != NULL)
+-        ctxt->depth = 0;
++        oldDepth = ctxt->depth;
+     xmlXPathCompileExpr(pctxt, 1);
++    if (ctxt != NULL)
++        ctxt->depth = oldDepth;
+ 
+     if( pctxt->error != XPATH_EXPRESSION_OK )
+     {
+@@ -14252,8 +14256,10 @@ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
+ 	comp = pctxt->comp;
+ 	if ((comp->nbStep > 1) && (comp->last >= 0)) {
+             if (ctxt != NULL)
+-                ctxt->depth = 0;
++                oldDepth = ctxt->depth;
+ 	    xmlXPathOptimizeExpression(pctxt, &comp->steps[comp->last]);
++            if (ctxt != NULL)
++                ctxt->depth = oldDepth;
+ 	}
+ 	pctxt->comp = NULL;
+     }
+@@ -14409,6 +14415,7 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
+ #ifdef XPATH_STREAMING
+     xmlXPathCompExprPtr comp;
+ #endif
++    int oldDepth = 0;
+ 
+     if (ctxt == NULL) return;
+ 
+@@ -14422,8 +14429,10 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
+ #endif
+     {
+         if (ctxt->context != NULL)
+-            ctxt->context->depth = 0;
++            oldDepth = ctxt->context->depth;
+ 	xmlXPathCompileExpr(ctxt, 1);
++        if (ctxt->context != NULL)
++            ctxt->context->depth = oldDepth;
+         CHECK_ERROR;
+ 
+         /* Check for trailing characters. */
+@@ -14432,9 +14441,11 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
+ 
+ 	if ((ctxt->comp->nbStep > 1) && (ctxt->comp->last >= 0)) {
+             if (ctxt->context != NULL)
+-                ctxt->context->depth = 0;
++                oldDepth = ctxt->context->depth;
+ 	    xmlXPathOptimizeExpression(ctxt,
+ 		&ctxt->comp->steps[ctxt->comp->last]);
++            if (ctxt->context != NULL)
++                ctxt->context->depth = oldDepth;
+         }
+     }
+ 
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-08-25 13:25:27.000000000 +0200
+++ libxml2-2.9.14+dfsg/debian/patches/series	2025-10-11 14:41:17.000000000 +0200
@@ -24,3 +24,4 @@
 CVE-2025-6170.patch
 CVE-2025-49794_CVE-2025-49796.patch
 CVE-2025-7425.patch
+CVE-2025-9714.patch

Attachment: signature.asc
Description: PGP signature


Reply to: