To address: - CVE-2025-24928 - CVE-2024-56171
From: Daniel Lehman dlehman25@gmail.com
To address: - CVE-2025-24928 - CVE-2024-56171 --- libs/xml2/include/libxml/xmlversion.h | 8 +-- libs/xml2/libxml.h | 12 +++-- libs/xml2/parser.c | 70 +++++++++++++++++++++++++++ libs/xml2/pattern.c | 4 +- libs/xml2/valid.c | 25 +++++----- libs/xml2/xmlschemas.c | 3 ++ libs/xml2/xpath.c | 5 +- 7 files changed, 104 insertions(+), 23 deletions(-)
diff --git a/libs/xml2/include/libxml/xmlversion.h b/libs/xml2/include/libxml/xmlversion.h index 36aa9ba0529..74e77b376f7 100644 --- a/libs/xml2/include/libxml/xmlversion.h +++ b/libs/xml2/include/libxml/xmlversion.h @@ -29,21 +29,21 @@ XMLPUBFUN void xmlCheckVersion(int version); * * the version string like "1.2.3" */ -#define LIBXML_DOTTED_VERSION "2.12.9" +#define LIBXML_DOTTED_VERSION "2.12.10"
/** * LIBXML_VERSION: * * the version number: 1.2.3 value is 10203 */ -#define LIBXML_VERSION 21209 +#define LIBXML_VERSION 21210
/** * LIBXML_VERSION_STRING: * * the version number string, 1.2.3 value is "10203" */ -#define LIBXML_VERSION_STRING "21209" +#define LIBXML_VERSION_STRING "21210"
/** * LIBXML_VERSION_EXTRA: @@ -58,7 +58,7 @@ XMLPUBFUN void xmlCheckVersion(int version); * Macro to check that the libxml version in use is compatible with * the version the software has been compiled against */ -#define LIBXML_TEST_VERSION xmlCheckVersion(21209); +#define LIBXML_TEST_VERSION xmlCheckVersion(21210);
#ifndef VMS #if 0 diff --git a/libs/xml2/libxml.h b/libs/xml2/libxml.h index eb84ebbfe06..bc0149c41a5 100644 --- a/libs/xml2/libxml.h +++ b/libs/xml2/libxml.h @@ -60,9 +60,15 @@ #endif
#ifdef __clang__ - #define ATTRIBUTE_NO_SANITIZE_INTEGER \ - ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") \ - ATTRIBUTE_NO_SANITIZE("unsigned-shift-base") + #if (!defined(__apple_build_version__) && __clang_major__ >= 12) || \ + (defined(__apple_build_version__) && __clang_major__ >= 13) + #define ATTRIBUTE_NO_SANITIZE_INTEGER \ + ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") \ + ATTRIBUTE_NO_SANITIZE("unsigned-shift-base") + #else + #define ATTRIBUTE_NO_SANITIZE_INTEGER \ + ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") + #endif #else #define ATTRIBUTE_NO_SANITIZE_INTEGER #endif diff --git a/libs/xml2/parser.c b/libs/xml2/parser.c index 9b8f349707d..3e8a588f536 100644 --- a/libs/xml2/parser.c +++ b/libs/xml2/parser.c @@ -9453,6 +9453,35 @@ xmlAttrHashInsert(xmlParserCtxtPtr ctxt, unsigned size, const xmlChar *name, return(INT_MAX); }
+static int +xmlAttrHashInsertQName(xmlParserCtxtPtr ctxt, unsigned size, + const xmlChar *name, const xmlChar *prefix, + unsigned hashValue, int aindex) { + xmlAttrHashBucket *table = ctxt->attrHash; + xmlAttrHashBucket *bucket; + unsigned hindex; + + hindex = hashValue & (size - 1); + bucket = &table[hindex]; + + while (bucket->index >= 0) { + const xmlChar **atts = &ctxt->atts[bucket->index]; + + if ((name == atts[0]) && (prefix == atts[1])) + return(bucket->index); + + hindex++; + bucket++; + if (hindex >= size) { + hindex = 0; + bucket = table; + } + } + + bucket->index = aindex; + + return(INT_MAX); +} /** * xmlParseStartTag2: * @ctxt: an XML parser context @@ -9501,6 +9530,8 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref, int nratts, nbatts, nbdef, inputid; int i, j, nbNs, nbTotalDef, attval, nsIndex, maxAtts; int alloc = 0; + int numNsErr = 0; + int numDupErr = 0;
if (RAW != '<') return(NULL); NEXT1; @@ -9879,10 +9910,12 @@ next_attr: if (res < INT_MAX) { if (aprefix == atts[res+1]) { xmlErrAttributeDup(ctxt, aprefix, attname); + numDupErr += 1; } else { xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED, "Namespaced Attribute %s in '%s' redefined\n", attname, nsuri, NULL); + numNsErr += 1; } } } @@ -9980,6 +10013,43 @@ next_attr: } }
+ /* + * Using a single hash table for nsUri/localName pairs cannot + * detect duplicate QNames reliably. The following example will + * only result in two namespace errors. + * + * <doc xmlns:a="a" xmlns:b="a"> + * <elem a:a="" b:a="" b:a=""/> + * </doc> + * + * If we saw more than one namespace error but no duplicate QNames + * were found, we have to scan for duplicate QNames. + */ + if ((numDupErr == 0) && (numNsErr > 1)) { + memset(ctxt->attrHash, -1, + attrHashSize * sizeof(ctxt->attrHash[0])); + + for (i = 0, j = 0; j < nratts; i += 5, j++) { + unsigned hashValue, nameHashValue, prefixHashValue; + int res; + + aprefix = atts[i+1]; + if (aprefix == NULL) + continue; + + attname = atts[i]; + /* Hash values always have bit 31 set, see dict.c */ + nameHashValue = ctxt->attallocs[j] | 0x80000000; + prefixHashValue = xmlDictComputeHash(ctxt->dict, aprefix); + + hashValue = xmlDictCombineHash(nameHashValue, prefixHashValue); + res = xmlAttrHashInsertQName(ctxt, attrHashSize, attname, + aprefix, hashValue, i); + if (res < INT_MAX) + xmlErrAttributeDup(ctxt, aprefix, attname); + } + } + /* * Reconstruct attribute pointers */ diff --git a/libs/xml2/pattern.c b/libs/xml2/pattern.c index 55ae2d3e5cf..b0f7f160141 100644 --- a/libs/xml2/pattern.c +++ b/libs/xml2/pattern.c @@ -1164,10 +1164,10 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { goto error; } } else { - PUSH(XML_OP_CHILD, token, URL); + PUSH(XML_OP_ELEM, token, URL); } } else - PUSH(XML_OP_CHILD, name, NULL); + PUSH(XML_OP_ELEM, name, NULL); return; } else if (xmlStrEqual(name, (const xmlChar *) "attribute")) { XML_PAT_FREE_STRING(ctxt, name) diff --git a/libs/xml2/valid.c b/libs/xml2/valid.c index 886485d67ea..ea3a65faac8 100644 --- a/libs/xml2/valid.c +++ b/libs/xml2/valid.c @@ -5057,25 +5057,26 @@ xmlSnprintfElements(char *buf, int size, xmlNodePtr node, int glob) { return; } switch (cur->type) { - case XML_ELEMENT_NODE: + case XML_ELEMENT_NODE: { + int qnameLen = xmlStrlen(cur->name); + + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) + qnameLen += xmlStrlen(cur->ns->prefix) + 1; + if (size - len < qnameLen + 10) { + if ((size - len > 4) && (buf[len - 1] != '.')) + strcat(buf, " ..."); + return; + } if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - if (size - len < xmlStrlen(cur->ns->prefix) + 10) { - if ((size - len > 4) && (buf[len - 1] != '.')) - strcat(buf, " ..."); - return; - } strcat(buf, (char *) cur->ns->prefix); strcat(buf, ":"); } - if (size - len < xmlStrlen(cur->name) + 10) { - if ((size - len > 4) && (buf[len - 1] != '.')) - strcat(buf, " ..."); - return; - } - strcat(buf, (char *) cur->name); + if (cur->name != NULL) + strcat(buf, (char *) cur->name); if (cur->next != NULL) strcat(buf, " "); break; + } case XML_TEXT_NODE: if (xmlIsBlankNode(cur)) break; diff --git a/libs/xml2/xmlschemas.c b/libs/xml2/xmlschemas.c index 886ff6e8c58..76cf6819687 100644 --- a/libs/xml2/xmlschemas.c +++ b/libs/xml2/xmlschemas.c @@ -23390,6 +23390,7 @@ xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt, } if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1) goto internal_error; + dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items; /* * Remove the duplicate entry from the IDC node-table. */ @@ -23606,6 +23607,8 @@ xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt) goto internal_error; } xmlSchemaItemListAdd(parBind->dupls, parNode); + dupls = (xmlSchemaPSVIIDCNodePtr *) + parBind->dupls->items; } else { /* * Add the node-table entry (node and key-sequence) of diff --git a/libs/xml2/xpath.c b/libs/xml2/xpath.c index 84514a83080..660d70e50fd 100644 --- a/libs/xml2/xpath.c +++ b/libs/xml2/xpath.c @@ -10714,8 +10714,9 @@ xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) { } else if (CUR == '/') { NEXT; SKIP_BLANKS; - if ((CUR != 0 ) && - ((IS_ASCII_LETTER(CUR)) || (CUR == '_') || (CUR == '.') || + if ((CUR != 0) && + ((IS_ASCII_LETTER(CUR)) || (CUR >= 0x80) || + (CUR == '_') || (CUR == '.') || (CUR == '@') || (CUR == '*'))) xmlXPathCompRelativeLocationPath(ctxt); }