From 3194d762dc6a80bca5d374fe5084888386fbadcd Mon Sep 17 00:00:00 2001
From: Snild Dolkow
+/* Added in Expat 2.6.0. */ +XML_Bool XMLCALL +XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled); ++
+ Large tokens may require many parse calls before enough data is available for Expat to parse it in full. + If Expat retried parsing the token on every parse call, parsing could take quadratic time. + To avoid this, Expat only retries once a significant amount of new data is available. + This function allows disabling this behavior. +
+
+ The enabled argument should be XML_TRUE or XML_FALSE.
+
+ Returns XML_TRUE on success, and XML_FALSE on error.
+
The functions in this section either obtain state information from diff --git a/lib/expat.h b/lib/expat.h index b7d6d354..a4033742 100644 --- a/lib/expat.h +++ b/lib/expat.h @@ -1036,6 +1036,10 @@ XML_SetBillionLaughsAttackProtectionActivationThreshold( XML_Parser parser, unsigned long long activationThresholdBytes); #endif +/* Added in Expat 2.6.0. */ +XMLPARSEAPI(XML_Bool) +XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled); + /* Expat follows the semantic versioning convention. See http://semver.org. */ diff --git a/lib/xmlparse.c b/lib/xmlparse.c index e30e76aa..d95b054b 100644 --- a/lib/xmlparse.c +++ b/lib/xmlparse.c @@ -617,6 +617,7 @@ struct XML_ParserStruct { XML_Index m_parseEndByteIndex; const char *m_parseEndPtr; size_t m_partialTokenBytesBefore; /* used in heuristic to avoid O(n^2) */ + XML_Bool m_reparseDeferralEnabled; XML_Char *m_dataBuf; XML_Char *m_dataBufEnd; XML_StartElementHandler m_startElementHandler; @@ -953,7 +954,7 @@ callProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { const size_t have_now = EXPAT_SAFE_PTR_DIFF(end, start); - if (g_reparseDeferralEnabledDefault + if (parser->m_reparseDeferralEnabled && ! parser->m_parsingStatus.finalBuffer) { // Heuristic: don't try to parse a partial token again until the amount of // available data has increased significantly. @@ -1149,6 +1150,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) { parser->m_parseEndByteIndex = 0; parser->m_parseEndPtr = NULL; parser->m_partialTokenBytesBefore = 0; + parser->m_reparseDeferralEnabled = g_reparseDeferralEnabledDefault; parser->m_declElementType = NULL; parser->m_declAttributeId = NULL; parser->m_declEntity = NULL; @@ -2568,6 +2570,15 @@ XML_SetBillionLaughsAttackProtectionActivationThreshold( } #endif /* defined(XML_DTD) || XML_GE == 1 */ +XML_Bool XMLCALL +XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled) { + if (parser != NULL && (enabled == XML_TRUE || enabled == XML_FALSE)) { + parser->m_reparseDeferralEnabled = enabled; + return XML_TRUE; + } + return XML_FALSE; +} + /* Initially tag->rawName always points into the parse buffer; for those TAG instances opened while the current parse buffer was processed, and not yet closed, we need to store tag->rawName in a more -- 2.33.0