Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP1:GA
libxml2
libxml2-CVE-2022-23308.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File libxml2-CVE-2022-23308.patch of Package libxml2
From 652dd12a858989b14eed4e84e453059cd3ba340e Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer <wellnhofer@aevum.de> Date: Tue, 8 Feb 2022 03:29:24 +0100 Subject: [PATCH] [CVE-2022-23308] Use-after-free of ID and IDREF attributes If a document is parsed with XML_PARSE_DTDVALID and without XML_PARSE_NOENT, the value of ID attributes has to be normalized after potentially expanding entities in xmlRemoveID. Otherwise, later calls to xmlGetID can return a pointer to previously freed memory. ID attributes which are empty or contain only whitespace after entity expansion are affected in a similar way. This is fixed by not storing such attributes in the ID table. The test to detect streaming mode when validating against a DTD was broken. In connection with the defects above, this could result in a use-after-free when using the xmlReader interface with validation. Fix detection of streaming mode to avoid similar issues. (This changes the expected result of a test case. But as far as I can tell, using the XML reader with XIncludes referencing the root document never worked properly, anyway.) All of these issues can result in denial of service. Using xmlReader with validation could result in disclosure of memory via the error channel, typically stderr. The security impact of xmlGetID returning a pointer to freed memory depends on the application. The typical use case of calling xmlGetID on an unmodified document is not affected. --- result/XInclude/ns1.xml.rdr | 2 +- valid.c | 88 +++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 34 deletions(-) Index: libxml2-2.9.7/valid.c =================================================================== --- libxml2-2.9.7.orig/valid.c +++ libxml2-2.9.7/valid.c @@ -479,6 +479,35 @@ nodeVPop(xmlValidCtxtPtr ctxt) return (ret); } +/** + * xmlValidNormalizeString: + * @str: a string + * + * Normalize a string in-place. + */ +static void +xmlValidNormalizeString(xmlChar *str) { + xmlChar *dst; + const xmlChar *src; + + if (str == NULL) + return; + src = str; + dst = str; + + while (*src == 0x20) src++; + while (*src != 0) { + if (*src == 0x20) { + while (*src == 0x20) src++; + if (*src != 0) + *dst++ = 0x20; + } else { + *dst++ = *src++; + } + } + *dst = 0; +} + #ifdef DEBUG_VALID_ALGO static void xmlValidPrintNode(xmlNodePtr cur) { @@ -2546,6 +2575,24 @@ xmlDumpNotationTable(xmlBufferPtr buf, x (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ xmlFree((char *)(str)); +static int +xmlIsStreaming(xmlValidCtxtPtr ctxt) { + xmlParserCtxtPtr pctxt; + + if (ctxt == NULL) + return(0); + /* + * These magic values are also abused to detect whether we're validating + * while parsing a document. In this case, userData points to the parser + * context. + */ + if ((ctxt->finishDtd != XML_CTXT_FINISH_DTD_0) && + (ctxt->finishDtd != XML_CTXT_FINISH_DTD_1)) + return(0); + pctxt = ctxt->userData; + return(pctxt->parseMode == XML_PARSE_READER); +} + /** * xmlFreeID: * @not: A id @@ -2589,7 +2636,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr if (doc == NULL) { return(NULL); } - if (value == NULL) { + if ((value == NULL) || (value[0] == 0)) { return(NULL); } if (attr == NULL) { @@ -2620,7 +2667,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr */ ret->value = xmlStrdup(value); ret->doc = doc; - if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { + if (xmlIsStreaming(ctxt)) { /* * Operating in streaming mode, attr is gonna disapear */ @@ -2754,6 +2801,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr at ID = xmlNodeListGetString(doc, attr->children, 1); if (ID == NULL) return(-1); + xmlValidNormalizeString(ID); id = xmlHashLookup(table, ID); if (id == NULL || id->attr != attr) { @@ -2942,7 +2990,7 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPt * fill the structure. */ ret->value = xmlStrdup(value); - if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { + if (xmlIsStreaming(ctxt)) { /* * Operating in streaming mode, attr is gonna disapear */ @@ -3962,8 +4010,7 @@ xmlValidateAttributeValue2(xmlValidCtxtP xmlChar * xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, const xmlChar *name, const xmlChar *value) { - xmlChar *ret, *dst; - const xmlChar *src; + xmlChar *ret; xmlAttributePtr attrDecl = NULL; int extsubset = 0; @@ -4004,19 +4051,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlV ret = xmlStrdup(value); if (ret == NULL) return(NULL); - src = value; - dst = ret; - while (*src == 0x20) src++; - while (*src != 0) { - if (*src == 0x20) { - while (*src == 0x20) src++; - if (*src != 0) - *dst++ = 0x20; - } else { - *dst++ = *src++; - } - } - *dst = 0; + xmlValidNormalizeString(ret); if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) { xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE, "standalone: %s on %s value had to be normalized based on external subset declaration\n", @@ -4048,8 +4083,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlV xmlChar * xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem, const xmlChar *name, const xmlChar *value) { - xmlChar *ret, *dst; - const xmlChar *src; + xmlChar *ret; xmlAttributePtr attrDecl = NULL; if (doc == NULL) return(NULL); @@ -4079,19 +4113,7 @@ xmlValidNormalizeAttributeValue(xmlDocPt ret = xmlStrdup(value); if (ret == NULL) return(NULL); - src = value; - dst = ret; - while (*src == 0x20) src++; - while (*src != 0) { - if (*src == 0x20) { - while (*src == 0x20) src++; - if (*src != 0) - *dst++ = 0x20; - } else { - *dst++ = *src++; - } - } - *dst = 0; + xmlValidNormalizeString(ret); return(ret); }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor