153aa9179Sopenharmony_ciFrom c50196c13d348025a4843305902bb37df64bae36 Mon Sep 17 00:00:00 2001 253aa9179Sopenharmony_ciFrom: David Kilzer <ddkilzer@apple.com> 353aa9179Sopenharmony_ciDate: Sun, 10 Apr 2022 20:02:47 -0700 453aa9179Sopenharmony_ciSubject: [PATCH 289/300] Fix use-after-free bugs when calling 553aa9179Sopenharmony_ci xmlTextReaderClose() before xmlFreeTextReader() on post-validating parser 653aa9179Sopenharmony_ci 753aa9179Sopenharmony_ciWhen creating an xmlTextReaderPtr using xmlReaderForMemory(), 853aa9179Sopenharmony_cithere are two optional API functions that can be used: 953aa9179Sopenharmony_ci- xmlTextReaderClose() may be called prior to calling 1053aa9179Sopenharmony_ci xmlFreeTextReader() to free parsing resources and close the 1153aa9179Sopenharmony_ci xmlTextReaderPtr without freeing it. 1253aa9179Sopenharmony_ci- xmlTextReaderCurrentDoc() may be called to return an 1353aa9179Sopenharmony_ci xmlDocPtr that's owned by the caller, and must be free using 1453aa9179Sopenharmony_ci xmlFreeDoc() after calling xmlFreeTextReader(). 1553aa9179Sopenharmony_ci 1653aa9179Sopenharmony_ciThe use-after-free issues occur when calling 1753aa9179Sopenharmony_cixmlTextReaderClose() before xmlFreeTextReader(), with different 1853aa9179Sopenharmony_ciissues occurring depending on whether xmlTextReaderCurrentDoc() 1953aa9179Sopenharmony_ciis also called. 2053aa9179Sopenharmony_ci 2153aa9179Sopenharmony_ci* xmlreader.c: 2253aa9179Sopenharmony_ci(xmlFreeTextReader): 2353aa9179Sopenharmony_ci- Move code to xmlTextReaderClose(), remove duplicate code, and 2453aa9179Sopenharmony_ci call xmlTextReaderClose() if it hasn't been called yet. 2553aa9179Sopenharmony_ci(xmlTextReaderClose): 2653aa9179Sopenharmony_ci- Move call to xmlFreeNode(reader->faketext) from 2753aa9179Sopenharmony_ci xmlFreeTextReader() to fix a use-after-free bug when calling 2853aa9179Sopenharmony_ci xmlTextReaderClose() before xmlFreeTextReader(), but not when 2953aa9179Sopenharmony_ci using xmlTextReaderCurrentDoc(). The bug was introduced in 3053aa9179Sopenharmony_ci 2002 by commit beb70bd39. In 2009 commit f4653dcd8 fixed the 3153aa9179Sopenharmony_ci use-after-free that occurred every time xmlFreeTextReader() 3253aa9179Sopenharmony_ci was called, but not the case where xmlTextReaderClose() was 3353aa9179Sopenharmony_ci called first. 3453aa9179Sopenharmony_ci- Move post-parsing validation code from xmlFreeTextReader() to 3553aa9179Sopenharmony_ci fix a second use-after-free when calling xmlTextReaderClose() 3653aa9179Sopenharmony_ci before xmlFreeTextReader(). This regressed in v2.9.10 with 3753aa9179Sopenharmony_ci commit 57a3af56f. 3853aa9179Sopenharmony_ci 3953aa9179Sopenharmony_ciReference:https://github.com/GNOME/libxml2/commit/c50196c13d348025a4843305902bb37df64bae36 4053aa9179Sopenharmony_ciConflict:NA 4153aa9179Sopenharmony_ci 4253aa9179Sopenharmony_ci--- 4353aa9179Sopenharmony_ci xmlreader.c | 40 ++++++++++++++++++---------------------- 4453aa9179Sopenharmony_ci 1 file changed, 18 insertions(+), 22 deletions(-) 4553aa9179Sopenharmony_ci 4653aa9179Sopenharmony_cidiff --git a/xmlreader.c b/xmlreader.c 4753aa9179Sopenharmony_ciindex 72e40b0..989b7c1 100644 4853aa9179Sopenharmony_ci--- a/xmlreader.c 4953aa9179Sopenharmony_ci+++ b/xmlreader.c 5053aa9179Sopenharmony_ci@@ -2319,36 +2319,16 @@ xmlFreeTextReader(xmlTextReaderPtr reader) { 5153aa9179Sopenharmony_ci xmlFree(reader->patternTab); 5253aa9179Sopenharmony_ci } 5353aa9179Sopenharmony_ci #endif 5453aa9179Sopenharmony_ci- if (reader->faketext != NULL) { 5553aa9179Sopenharmony_ci- xmlFreeNode(reader->faketext); 5653aa9179Sopenharmony_ci- } 5753aa9179Sopenharmony_ci+ if (reader->mode != XML_TEXTREADER_MODE_CLOSED) 5853aa9179Sopenharmony_ci+ xmlTextReaderClose(reader); 5953aa9179Sopenharmony_ci if (reader->ctxt != NULL) { 6053aa9179Sopenharmony_ci if (reader->dict == reader->ctxt->dict) 6153aa9179Sopenharmony_ci reader->dict = NULL; 6253aa9179Sopenharmony_ci-#ifdef LIBXML_VALID_ENABLED 6353aa9179Sopenharmony_ci- if ((reader->ctxt->vctxt.vstateTab != NULL) && 6453aa9179Sopenharmony_ci- (reader->ctxt->vctxt.vstateMax > 0)){ 6553aa9179Sopenharmony_ci-#ifdef LIBXML_REGEXP_ENABLED 6653aa9179Sopenharmony_ci- while (reader->ctxt->vctxt.vstateNr > 0) 6753aa9179Sopenharmony_ci- xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL); 6853aa9179Sopenharmony_ci-#endif /* LIBXML_REGEXP_ENABLED */ 6953aa9179Sopenharmony_ci- xmlFree(reader->ctxt->vctxt.vstateTab); 7053aa9179Sopenharmony_ci- reader->ctxt->vctxt.vstateTab = NULL; 7153aa9179Sopenharmony_ci- reader->ctxt->vctxt.vstateMax = 0; 7253aa9179Sopenharmony_ci- } 7353aa9179Sopenharmony_ci-#endif /* LIBXML_VALID_ENABLED */ 7453aa9179Sopenharmony_ci- if (reader->ctxt->myDoc != NULL) { 7553aa9179Sopenharmony_ci- if (reader->preserve == 0) 7653aa9179Sopenharmony_ci- xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); 7753aa9179Sopenharmony_ci- reader->ctxt->myDoc = NULL; 7853aa9179Sopenharmony_ci- } 7953aa9179Sopenharmony_ci if (reader->allocs & XML_TEXTREADER_CTXT) 8053aa9179Sopenharmony_ci xmlFreeParserCtxt(reader->ctxt); 8153aa9179Sopenharmony_ci } 8253aa9179Sopenharmony_ci if (reader->sax != NULL) 8353aa9179Sopenharmony_ci xmlFree(reader->sax); 8453aa9179Sopenharmony_ci- if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) 8553aa9179Sopenharmony_ci- xmlFreeParserInputBuffer(reader->input); 8653aa9179Sopenharmony_ci if (reader->buffer != NULL) 8753aa9179Sopenharmony_ci xmlBufFree(reader->buffer); 8853aa9179Sopenharmony_ci if (reader->entTab != NULL) 8953aa9179Sopenharmony_ci@@ -2379,7 +2359,23 @@ xmlTextReaderClose(xmlTextReaderPtr reader) { 9053aa9179Sopenharmony_ci reader->node = NULL; 9153aa9179Sopenharmony_ci reader->curnode = NULL; 9253aa9179Sopenharmony_ci reader->mode = XML_TEXTREADER_MODE_CLOSED; 9353aa9179Sopenharmony_ci+ if (reader->faketext != NULL) { 9453aa9179Sopenharmony_ci+ xmlFreeNode(reader->faketext); 9553aa9179Sopenharmony_ci+ reader->faketext = NULL; 9653aa9179Sopenharmony_ci+ } 9753aa9179Sopenharmony_ci if (reader->ctxt != NULL) { 9853aa9179Sopenharmony_ci+#ifdef LIBXML_VALID_ENABLED 9953aa9179Sopenharmony_ci+ if ((reader->ctxt->vctxt.vstateTab != NULL) && 10053aa9179Sopenharmony_ci+ (reader->ctxt->vctxt.vstateMax > 0)){ 10153aa9179Sopenharmony_ci+#ifdef LIBXML_REGEXP_ENABLED 10253aa9179Sopenharmony_ci+ while (reader->ctxt->vctxt.vstateNr > 0) 10353aa9179Sopenharmony_ci+ xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL); 10453aa9179Sopenharmony_ci+#endif /* LIBXML_REGEXP_ENABLED */ 10553aa9179Sopenharmony_ci+ xmlFree(reader->ctxt->vctxt.vstateTab); 10653aa9179Sopenharmony_ci+ reader->ctxt->vctxt.vstateTab = NULL; 10753aa9179Sopenharmony_ci+ reader->ctxt->vctxt.vstateMax = 0; 10853aa9179Sopenharmony_ci+ } 10953aa9179Sopenharmony_ci+#endif /* LIBXML_VALID_ENABLED */ 11053aa9179Sopenharmony_ci xmlStopParser(reader->ctxt); 11153aa9179Sopenharmony_ci if (reader->ctxt->myDoc != NULL) { 11253aa9179Sopenharmony_ci if (reader->preserve == 0) 11353aa9179Sopenharmony_ci-- 11453aa9179Sopenharmony_ci2.27.0 11553aa9179Sopenharmony_ci 116