113 lines
3.8 KiB
Diff
113 lines
3.8 KiB
Diff
From 847a3a1181d59dc49c1b446d646d344d0543af3e Mon Sep 17 00:00:00 2001
|
|
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
Date: Mon, 28 Sep 2020 12:28:29 +0200
|
|
Subject: [PATCH] Fix use-after-free when XIncluding text from Reader
|
|
|
|
The XML Reader can free text nodes coming from the XInclude engine
|
|
before parsing has finished. Cache a copy of the text string, not the
|
|
included node to avoid use after free.
|
|
|
|
Found by OSS-Fuzz.
|
|
---
|
|
xinclude.c | 31 ++++++++++++++++++-------------
|
|
1 file changed, 18 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/xinclude.c b/xinclude.c
|
|
index f48e0af5..1636caff 100644
|
|
--- a/xinclude.c
|
|
+++ b/xinclude.c
|
|
@@ -72,7 +72,7 @@ struct _xmlXIncludeCtxt {
|
|
|
|
int txtNr; /* number of unparsed documents */
|
|
int txtMax; /* size of unparsed documents tab */
|
|
- xmlNodePtr *txtTab; /* array of unparsed text nodes */
|
|
+ xmlChar * *txtTab; /* array of unparsed text strings */
|
|
xmlURL *txturlTab; /* array of unparsed text URLs */
|
|
|
|
xmlChar * url; /* the current URL processed */
|
|
@@ -393,18 +393,22 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
|
|
if (ctxt->incTab[i] != NULL)
|
|
xmlXIncludeFreeRef(ctxt->incTab[i]);
|
|
}
|
|
+ if (ctxt->incTab != NULL)
|
|
+ xmlFree(ctxt->incTab);
|
|
+ if (ctxt->txtTab != NULL) {
|
|
+ for (i = 0;i < ctxt->txtNr;i++) {
|
|
+ if (ctxt->txtTab[i] != NULL)
|
|
+ xmlFree(ctxt->txtTab[i]);
|
|
+ }
|
|
+ xmlFree(ctxt->txtTab);
|
|
+ }
|
|
if (ctxt->txturlTab != NULL) {
|
|
for (i = 0;i < ctxt->txtNr;i++) {
|
|
if (ctxt->txturlTab[i] != NULL)
|
|
xmlFree(ctxt->txturlTab[i]);
|
|
}
|
|
- }
|
|
- if (ctxt->incTab != NULL)
|
|
- xmlFree(ctxt->incTab);
|
|
- if (ctxt->txtTab != NULL)
|
|
- xmlFree(ctxt->txtTab);
|
|
- if (ctxt->txturlTab != NULL)
|
|
xmlFree(ctxt->txturlTab);
|
|
+ }
|
|
if (ctxt->base != NULL) {
|
|
xmlFree(ctxt->base);
|
|
}
|
|
@@ -764,13 +768,14 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
|
|
* Add a new text node to the list
|
|
*/
|
|
static void
|
|
-xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
|
|
+xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *txt,
|
|
+ const xmlURL url) {
|
|
#ifdef DEBUG_XINCLUDE
|
|
xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
|
|
#endif
|
|
if (ctxt->txtMax == 0) {
|
|
ctxt->txtMax = 4;
|
|
- ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
|
|
+ ctxt->txtTab = (xmlChar **) xmlMalloc(ctxt->txtMax *
|
|
sizeof(ctxt->txtTab[0]));
|
|
if (ctxt->txtTab == NULL) {
|
|
xmlXIncludeErrMemory(ctxt, NULL, "processing text");
|
|
@@ -785,7 +790,7 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
|
|
}
|
|
if (ctxt->txtNr >= ctxt->txtMax) {
|
|
ctxt->txtMax *= 2;
|
|
- ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
|
|
+ ctxt->txtTab = (xmlChar **) xmlRealloc(ctxt->txtTab,
|
|
ctxt->txtMax * sizeof(ctxt->txtTab[0]));
|
|
if (ctxt->txtTab == NULL) {
|
|
xmlXIncludeErrMemory(ctxt, NULL, "processing text");
|
|
@@ -798,7 +803,7 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
|
|
return;
|
|
}
|
|
}
|
|
- ctxt->txtTab[ctxt->txtNr] = txt;
|
|
+ ctxt->txtTab[ctxt->txtNr] = xmlStrdup(txt);
|
|
ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
|
|
ctxt->txtNr++;
|
|
}
|
|
@@ -1845,7 +1850,7 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
|
|
*/
|
|
for (i = 0; i < ctxt->txtNr; i++) {
|
|
if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
|
|
- node = xmlCopyNode(ctxt->txtTab[i], 1);
|
|
+ node = xmlNewText(ctxt->txtTab[i]);
|
|
goto loaded;
|
|
}
|
|
}
|
|
@@ -1935,7 +1940,7 @@ xinclude_multibyte_fallback:
|
|
xmlBufShrink(buf->buffer, len);
|
|
}
|
|
xmlFreeParserCtxt(pctxt);
|
|
- xmlXIncludeAddTxt(ctxt, node, URL);
|
|
+ xmlXIncludeAddTxt(ctxt, node->content, URL);
|
|
xmlFreeInputStream(inputStream);
|
|
|
|
loaded:
|
|
--
|
|
2.27.0
|
|
|