From 08ff7591ffe9519f627e246f841427c6f10edc2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= Date: Tue, 15 Oct 2024 11:37:09 +0200 Subject: [PATCH] Fix entity debug order The fix for entity processing changes the order of opening and closing of entities. The reason is the new iterative approach that closes and removes entities as soon as they are fully processed, unlike the recursive approach that, as a side effect of the recursion, waits the inner entities before closing and removal. This commit delays the removal and the call to entityTrackingOnClose until the current entities inner entities are processed, which in turn allows us to have the correct debug order again. Reference: https://github.com/libexpat/libexpat/pull/973/commits/c20ce3aaa3a114e7d671d11625a63d75de904e31 Conflict: adapt internalEntityProcessor --- lib/xmlparse.c | 121 ++++++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 57 deletions(-) diff --git a/lib/xmlparse.c b/lib/xmlparse.c index 9dda309..325d5e7 100644 --- a/lib/xmlparse.c +++ b/lib/xmlparse.c @@ -6004,38 +6004,46 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, return XML_ERROR_UNEXPECTED_STATE; entity = openEntity->entity; - textStart = ((const char *)entity->textPtr) + entity->processed; - textEnd = (const char *)(entity->textPtr + entity->textLen); - /* Set a safe default value in case 'next' does not get set */ - next = textStart; + if (entity->open) { + textStart = ((const char *)entity->textPtr) + entity->processed; + textEnd = (const char *)(entity->textPtr + entity->textLen); + /* Set a safe default value in case 'next' does not get set */ + next = textStart; #ifdef XML_DTD - if (entity->is_param) { - int tok - = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next); - result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, - tok, next, &next, XML_FALSE, XML_FALSE, - XML_ACCOUNT_ENTITY_EXPANSION); - } else + if (entity->is_param) { + int tok + = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next); + result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, + tok, next, &next, XML_FALSE, XML_FALSE, + XML_ACCOUNT_ENTITY_EXPANSION); + } else { #endif /* XML_DTD */ - result = doContent(parser, openEntity->startTagLevel, - parser->m_internalEncoding, textStart, textEnd, &next, - XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION); + result = doContent(parser, openEntity->startTagLevel, + parser->m_internalEncoding, textStart, textEnd, &next, + XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION); + } - if (result != XML_ERROR_NONE) - return result; - if (textEnd != next - && (parser->m_parsingStatus.parsing == XML_SUSPENDED - || (parser->m_parsingStatus.parsing == XML_PARSING - && parser->m_reenter))) { - entity->processed = (int)(next - (const char *)entity->textPtr); + if (result != XML_ERROR_NONE) + return result; + // Check if entity is complete, if not, mark down how much of it is + // processed + if (textEnd != next + && (parser->m_parsingStatus.parsing == XML_SUSPENDED + || (parser->m_parsingStatus.parsing == XML_PARSING + && parser->m_reenter))) { + entity->processed = (int)(next - (const char *)entity->textPtr); + return result; + } + + entity->open = XML_FALSE; + triggerReenter(parser); return result; } #if defined(XML_DTD) || XML_GE == 1 entityTrackingOnClose(parser, entity, __LINE__); #endif - entity->open = XML_FALSE; // Remove fully processed openEntity from open entity list. doContent call can // add maximum one new entity to m_openInternalEntities since when a new // entity is detected, parser will go into REENTER state and return. Therefore @@ -6053,19 +6061,6 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, openEntity->next = parser->m_freeInternalEntities; parser->m_freeInternalEntities = openEntity; - // If the state is XML_SUSPENDED and there are more open entities we want to - // stop right here and have the upcoming call to XML_ResumeParser continue - // with entity content, or it would be ignored altogether. - // If the state is XML_PARSING, m_reenter is set, and there are more open - // entities, we want to return and reenter to internalEntityProcessor to - // process the next entity in the list - if (parser->m_openInternalEntities != NULL - && (parser->m_parsingStatus.parsing == XML_SUSPENDED - || (parser->m_parsingStatus.parsing == XML_PARSING - && parser->m_reenter))) { - return XML_ERROR_NONE; - } - if (parser->m_openInternalEntities == NULL) { parser->m_processor = entity->is_param ? prologProcessor : contentProcessor; // internalEntityProcessor is called from callProcessor's while(1) loop, @@ -6113,23 +6108,29 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, = (const char *)(entity->textPtr + entity->textLen); /* Set a safe default value in case 'next' does not get set */ const char *nextInEntity = textStart; - result = appendAttributeValue( - parser, parser->m_internalEncoding, isCdata, textStart, textEnd, pool, - XML_ACCOUNT_ENTITY_EXPANSION, &nextInEntity); - if (result != XML_ERROR_NONE) - break; - // Check if entity is complete, if not, mark down how much of it is - // processed. A XML_SUSPENDED check here is not required as - // appendAttributeValue will never suspend the parser. - if (textEnd != nextInEntity) { - entity->processed = (int)(nextInEntity - (const char *)entity->textPtr); + if (entity->open) { + result = appendAttributeValue( + parser, parser->m_internalEncoding, isCdata, textStart, textEnd, + pool, XML_ACCOUNT_ENTITY_EXPANSION, &nextInEntity); + if (result != XML_ERROR_NONE) + break; + // Check if entity is complete, if not, mark down how much of it is + // processed. A XML_SUSPENDED check here is not required as + // appendAttributeValue will never suspend the parser. + if (textEnd != nextInEntity) { + entity->processed + = (int)(nextInEntity - (const char *)entity->textPtr); + continue; + } + + entity->open = XML_FALSE; + triggerReenter(parser); continue; } #if XML_GE == 1 entityTrackingOnClose(parser, entity, __LINE__); #endif - entity->open = XML_FALSE; // Remove fully processed openEntity from open entity list. // appendAttributeValue call can add maximum one new entity to // m_openAttributeEntities since when a new entity is detected, parser @@ -6566,23 +6567,29 @@ callStoreEntityValue(XML_Parser parser, const ENCODING *enc, = (const char *)(entity->textPtr + entity->textLen); /* Set a safe default value in case 'next' does not get set */ const char *nextInEntity = textStart; - result = storeEntityValue(parser, parser->m_internalEncoding, textStart, - textEnd, XML_ACCOUNT_ENTITY_EXPANSION, - &nextInEntity); - if (result != XML_ERROR_NONE) - break; - // Check if entity is complete, if not, mark down how much of it is - // processed. A XML_SUSPENDED check here is not required as - // appendAttributeValue will never suspend the parser. - if (textEnd != nextInEntity) { - entity->processed = (int)(nextInEntity - (const char *)entity->textPtr); + if (entity->open) { + result = storeEntityValue(parser, parser->m_internalEncoding, textStart, + textEnd, XML_ACCOUNT_ENTITY_EXPANSION, + &nextInEntity); + if (result != XML_ERROR_NONE) + break; + // Check if entity is complete, if not, mark down how much of it is + // processed. A XML_SUSPENDED check here is not required as + // appendAttributeValue will never suspend the parser. + if (textEnd != nextInEntity) { + entity->processed + = (int)(nextInEntity - (const char *)entity->textPtr); + continue; + } + + entity->open = XML_FALSE; + triggerReenter(parser); continue; } # if XML_GE == 1 entityTrackingOnClose(parser, entity, __LINE__); # endif - entity->open = XML_FALSE; // Remove fully processed openEntity from open entity list. // appendAttributeValue call can add maximum one new entity to // m_openValueEntities since when a new entity is detected, parser -- 2.33.0