diff options
author | Nick Wellnhofer <wellnhofer@aevum.de> | 2020-09-28 12:28:29 +0200 |
---|---|---|
committer | Nick Wellnhofer <wellnhofer@aevum.de> | 2020-09-28 12:37:51 +0200 |
commit | 847a3a1181d59dc49c1b446d646d344d0543af3e (patch) | |
tree | 54d6ecb6ae899468140df0a54ec9ec0bc7c36636 /xinclude.c | |
parent | 7929f05710134b9b243952019b6c14066cd3ac9e (diff) | |
download | libxml2-847a3a1181d59dc49c1b446d646d344d0543af3e.tar.gz |
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.
Diffstat (limited to 'xinclude.c')
-rw-r--r-- | xinclude.c | 31 |
1 files changed, 18 insertions, 13 deletions
@@ -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: |