Description
Pull request #616 titles "Bugfixes" contains two bug reports. This new ticket is about the "UAF due to DTD destruction" half of it, with the intention of making the issue more easily accessible.
If I squash together the two related commits…
…we get a single commit with this bug description…
If the allocation in
parserInitfails:parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));Then we'll call
XML_ParserFreeon the parser insideparserCreate:if (encodingName && ! parser->m_protocolEncodingName) { XML_ParserFree(parser); return NULL; }If we're inside
XML_ExternalEntityParserCreate, this can mean thatXML_ParserFreeis called on a parser whosem_dtdpointer is shared with the document's root parser. Since the flagm_isParamEntityis only set inXML_ExternalEntityParserCreateafterparserCreatereturns, this call toXML_ParserFreewill incorrectly destroy the shared dtd.This fix moves the setting of
m_isParamEntityintoparserCreate, since the dtd parameter is only non-NULL in this case.
and this candidate patch for review:
--- a/expat/lib/xmlparse.c
+++ b/expat/lib/xmlparse.c
@@ -1028,10 +1028,16 @@ parserCreate(const XML_Char *encodingName,
}
parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE;
- if (dtd)
+ if (dtd) {
parser->m_dtd = dtd;
- else {
+#ifdef XML_DTD
+ parser->m_isParamEntity = XML_TRUE;
+#endif
+ } else {
parser->m_dtd = dtdCreate(&parser->m_mem);
+#ifdef XML_DTD
+ parser->m_isParamEntity = XML_FALSE;
+#endif
if (parser->m_dtd == NULL) {
FREE(parser, parser->m_dataBuf);
FREE(parser, parser->m_atts);
@@ -1148,7 +1154,6 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_parentParser = NULL;
parser->m_parsingStatus.parsing = XML_INITIALIZED;
#ifdef XML_DTD
- parser->m_isParamEntity = XML_FALSE;
parser->m_useForeignDTD = XML_FALSE;
parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
#endif
@@ -1406,7 +1411,6 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
pointers in parser->m_dtd with ones that get destroyed with the external
PE parser. This would leave those prefixes with dangling pointers.
*/
- parser->m_isParamEntity = XML_TRUE;
XmlPrologStateInitExternalEntity(&parser->m_prologState);
parser->m_processor = externalParEntInitProcessor;
}CC @c01db33f