Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: cherry-pick 652dd12a85 from chromium
- Loading branch information
Showing
3 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: Nick Wellnhofer <wellnhofer@aevum.de> | ||
Date: Tue, 22 Feb 2022 11:51:08 +0100 | ||
Subject: Fix --without-valid build | ||
|
||
Regressed in commit 652dd12a. | ||
|
||
diff --git a/third_party/libxml/src/valid.c b/third_party/libxml/src/valid.c | ||
index 8e596f1db3db40a5decc5f4b529abc7588c6bd66..9684683a08018ca1185f85414f358791bfb1264b 100644 | ||
--- a/third_party/libxml/src/valid.c | ||
+++ b/third_party/libxml/src/valid.c | ||
@@ -479,35 +479,6 @@ 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) { | ||
@@ -2636,6 +2607,35 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) { | ||
(xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ | ||
xmlFree((char *)(str)); | ||
|
||
+/** | ||
+ * 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; | ||
+} | ||
+ | ||
static int | ||
xmlIsStreaming(xmlValidCtxtPtr ctxt) { | ||
xmlParserCtxtPtr pctxt; |
190 changes: 190 additions & 0 deletions
190
patches/chromium/use-after-free_of_id_and_idref_attributes.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: Nick Wellnhofer <wellnhofer@aevum.de> | ||
Date: Tue, 8 Feb 2022 03:29:24 +0100 | ||
Subject: 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. | ||
|
||
diff --git a/third_party/libxml/src/valid.c b/third_party/libxml/src/valid.c | ||
index 5ee391c0418327f5e46293aedafdb353550f6f5b..8e596f1db3db40a5decc5f4b529abc7588c6bd66 100644 | ||
--- a/third_party/libxml/src/valid.c | ||
+++ b/third_party/libxml/src/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) { | ||
@@ -2607,6 +2636,24 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) { | ||
(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 | ||
@@ -2650,7 +2697,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, | ||
if (doc == NULL) { | ||
return(NULL); | ||
} | ||
- if (value == NULL) { | ||
+ if ((value == NULL) || (value[0] == 0)) { | ||
return(NULL); | ||
} | ||
if (attr == NULL) { | ||
@@ -2681,7 +2728,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, | ||
*/ | ||
ret->value = xmlStrdup(value); | ||
ret->doc = doc; | ||
- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { | ||
+ if (xmlIsStreaming(ctxt)) { | ||
/* | ||
* Operating in streaming mode, attr is gonna disappear | ||
*/ | ||
@@ -2820,6 +2867,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) { | ||
ID = xmlNodeListGetString(doc, attr->children, 1); | ||
if (ID == NULL) | ||
return(-1); | ||
+ xmlValidNormalizeString(ID); | ||
|
||
id = xmlHashLookup(table, ID); | ||
if (id == NULL || id->attr != attr) { | ||
@@ -3009,7 +3057,7 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, | ||
* fill the structure. | ||
*/ | ||
ret->value = xmlStrdup(value); | ||
- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { | ||
+ if (xmlIsStreaming(ctxt)) { | ||
/* | ||
* Operating in streaming mode, attr is gonna disappear | ||
*/ | ||
@@ -4028,8 +4076,7 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc, | ||
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; | ||
|
||
@@ -4070,19 +4117,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, | ||
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", | ||
@@ -4114,8 +4149,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, | ||
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); | ||
@@ -4145,19 +4179,7 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem, | ||
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); | ||
} | ||
|