fix CVE-2024-8176

This commit is contained in:
zhuofeng 2025-03-29 17:01:17 +08:00 committed by root
parent b908834a6e
commit 2fc4b29f0d
12 changed files with 1715 additions and 1 deletions

View File

@ -0,0 +1,202 @@
From cf6dc8e885feef5d5ce2225bd1d2c535162b7e39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
Date: Sat, 10 Aug 2024 21:00:00 +0200
Subject: [PATCH] Introduce reenter flag
Co-authored-by: Jann Horn <jannh@google.com>
Add a new reenter flag. This flag acts like XML_SUSPENDED,
except that instead of returning out of the library, we
only return back to the main parse function, then re-enter
the processor function.
---
lib/xmlparse.c | 88 ++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 79 insertions(+), 9 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index e13b2bf..a94aa38 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -716,6 +716,7 @@ struct XML_ParserStruct {
ACCOUNTING m_accounting;
ENTITY_STATS m_entity_stats;
#endif
+ XML_Bool m_reenter;
};
#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
@@ -974,7 +975,28 @@ callProcessor(XML_Parser parser, const char *start, const char *end,
return XML_ERROR_NONE;
}
}
- const enum XML_Error ret = parser->m_processor(parser, start, end, endPtr);
+ // Run in a loop to eliminate dangerous recursion depths
+ enum XML_Error ret;
+ *endPtr = start;
+ while (1) {
+ // Use endPtr as the new start in each iteration, since it will
+ // be set to the next start point by m_processor.
+ ret = parser->m_processor(parser, *endPtr, end, endPtr);
+
+ // Make parsing status (and in particular XML_SUSPENDED) take
+ // precedence over re-enter flag when they disagree
+ if (parser->m_parsingStatus.parsing != XML_PARSING) {
+ parser->m_reenter = XML_FALSE;
+ }
+
+ if (! parser->m_reenter) {
+ break;
+ }
+
+ parser->m_reenter = XML_FALSE;
+ if (ret != XML_ERROR_NONE)
+ return ret;
+ }
if (ret == XML_ERROR_NONE) {
// if we consumed nothing, remember what we had on this parse attempt.
if (*endPtr == start) {
@@ -1196,6 +1218,8 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_unknownEncodingData = NULL;
parser->m_parentParser = NULL;
parser->m_parsingStatus.parsing = XML_INITIALIZED;
+ // Reentry can only be triggered inside m_processor calls
+ parser->m_reenter = XML_FALSE;
#ifdef XML_DTD
parser->m_isParamEntity = XML_FALSE;
parser->m_useForeignDTD = XML_FALSE;
@@ -2203,6 +2227,11 @@ XML_GetBuffer(XML_Parser parser, int len) {
return parser->m_bufferEnd;
}
+static void
+triggerReenter(XML_Parser parser) {
+ parser->m_reenter = XML_TRUE;
+}
+
enum XML_Status XMLCALL
XML_StopParser(XML_Parser parser, XML_Bool resumable) {
if (parser == NULL)
@@ -2764,6 +2793,12 @@ externalEntityInitProcessor3(XML_Parser parser, const char *start,
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
+ case XML_PARSING:
+ if (parser->m_reenter) {
+ *endPtr = next;
+ return XML_ERROR_NONE;
+ }
+ /* Fall through */
default:
start = next;
}
@@ -3063,7 +3098,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
}
if ((parser->m_tagLevel == 0)
&& (parser->m_parsingStatus.parsing != XML_FINISHED)) {
- if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
+ if (parser->m_parsingStatus.parsing == XML_SUSPENDED
+ || (parser->m_parsingStatus.parsing == XML_PARSING
+ && parser->m_reenter))
parser->m_processor = epilogProcessor;
else
return epilogProcessor(parser, next, end, nextPtr);
@@ -3124,7 +3161,9 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
}
if ((parser->m_tagLevel == 0)
&& (parser->m_parsingStatus.parsing != XML_FINISHED)) {
- if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
+ if (parser->m_parsingStatus.parsing == XML_SUSPENDED
+ || (parser->m_parsingStatus.parsing == XML_PARSING
+ && parser->m_reenter))
parser->m_processor = epilogProcessor;
else
return epilogProcessor(parser, next, end, nextPtr);
@@ -3264,6 +3303,12 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
+ case XML_PARSING:
+ if (parser->m_reenter) {
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ }
+ /* Fall through */
default:;
}
}
@@ -4188,6 +4233,12 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
+ case XML_PARSING:
+ if (parser->m_reenter) {
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ }
+ /* Fall through */
default:;
}
}
@@ -5722,6 +5773,12 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
+ case XML_PARSING:
+ if (parser->m_reenter) {
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ }
+ /* Fall through */
default:
s = next;
tok = XmlPrologTok(enc, s, end, &next);
@@ -5796,6 +5853,12 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
+ case XML_PARSING:
+ if (parser->m_reenter) {
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ }
+ /* Fall through */
default:;
}
}
@@ -5897,8 +5960,10 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
if (result != XML_ERROR_NONE)
return result;
-
- if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
+ 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;
}
@@ -5912,11 +5977,16 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
openEntity->next = parser->m_freeInternalEntities;
parser->m_freeInternalEntities = openEntity;
- // If 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_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_SUSPENDED
+ || (parser->m_parsingStatus.parsing == XML_PARSING
+ && parser->m_reenter))) {
return XML_ERROR_NONE;
}
--
2.33.0

View File

@ -0,0 +1,31 @@
From 6edca2c37e280b3ce15e776ffabf70f11abf2966 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
Date: Thu, 12 Dec 2024 14:06:44 +0100
Subject: [PATCH 2/7] Switch allowClosingDoctype
This change of allowClosingDoctype has no effect and only serves as a
preparation for the upcoming changes.
Reference: https://github.com/libexpat/libexpat/pull/973/commits/6edca2c37e280b3ce15e776ffabf70f11abf2966
Conflict: adapt internalEntityProcessor
---
lib/xmlparse.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 29843b0..10225e3 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -5944,7 +5944,7 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
int tok
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
- tok, next, &next, XML_FALSE, XML_TRUE,
+ tok, next, &next, XML_FALSE, XML_FALSE,
XML_ACCOUNT_ENTITY_EXPANSION);
} else
#endif /* XML_DTD */
--
2.33.0

View File

@ -0,0 +1,163 @@
From 95aa319b65b97d8a0abb5a2eda6295c3047f2bf9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
Date: Sun, 11 Aug 2024 21:00:00 +0200
Subject: [PATCH] Fix internal entity processing
Co-authored-by: Jann Horn <jannh@google.com>
This avoids unbounded recursion in internal entity processing
Reference: https://github.com/libexpat/libexpat/pull/973/commits/a910fbc0e1c3828702c75001647ea98b06f8acd9
Conflict: adapt processInternalEntity, internalEntityProcessor
---
lib/xmlparse.c | 91 +++++++++++++++++---------------------------------
1 file changed, 31 insertions(+), 60 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 9de7676..a6f1ce2 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -2704,8 +2704,9 @@ static enum XML_Error PTRCALL
contentProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
enum XML_Error result = doContent(
- parser, 0, parser->m_encoding, start, end, endPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
+ parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, start, end,
+ endPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer,
+ XML_ACCOUNT_DIRECT);
if (result == XML_ERROR_NONE) {
if (! storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
@@ -5866,9 +5867,6 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
static enum XML_Error
processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
- const char *textStart, *textEnd;
- const char *next;
- enum XML_Error result;
OPEN_INTERNAL_ENTITY *openEntity;
if (parser->m_freeInternalEntities) {
@@ -5885,6 +5883,7 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
entityTrackingOnOpen(parser, entity, __LINE__);
#endif
entity->processed = 0;
+ parser->m_processor = internalEntityProcessor;
openEntity->next = parser->m_openInternalEntities;
parser->m_openInternalEntities = openEntity;
openEntity->entity = entity;
@@ -5892,45 +5891,15 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
openEntity->betweenDecl = betweenDecl;
openEntity->internalEventPtr = NULL;
openEntity->internalEventEndPtr = NULL;
- textStart = (const char *)entity->textPtr;
- 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
-#endif /* XML_DTD */
- result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
- textStart, textEnd, &next, XML_FALSE,
- XML_ACCOUNT_ENTITY_EXPANSION);
- if (result == XML_ERROR_NONE) {
- if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
- entity->processed = (int)(next - textStart);
- parser->m_processor = internalEntityProcessor;
- } else {
-#if defined(XML_DTD) || XML_GE == 1
- entityTrackingOnClose(parser, entity, __LINE__);
-#endif /* defined(XML_DTD) || XML_GE == 1 */
- entity->open = XML_FALSE;
- parser->m_openInternalEntities = openEntity->next;
- /* put openEntity back in list of free instances */
- openEntity->next = parser->m_freeInternalEntities;
- parser->m_freeInternalEntities = openEntity;
- }
- }
- return result;
+ triggerReenter(parser);
+ return XML_ERROR_NONE;
}
static enum XML_Error PTRCALL
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
+ UNUSED_P(s);
ENTITY *entity;
const char *textStart, *textEnd;
const char *next;
@@ -5972,7 +5941,19 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
entityTrackingOnClose(parser, entity, __LINE__);
#endif
entity->open = XML_FALSE;
- parser->m_openInternalEntities = openEntity->next;
+ // 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
+ // openEntity is either the head or next to the new head.
+ if (parser->m_openInternalEntities == openEntity) {
+ // No new entity detected during entity processing,
+ // openEntity is still the head.
+ parser->m_openInternalEntities = parser->m_openInternalEntities->next;
+ } else {
+ // New entity detected since list has a new head. openEntity is the second
+ // element.
+ parser->m_openInternalEntities->next = openEntity->next;
+ }
/* put openEntity back in list of free instances */
openEntity->next = parser->m_freeInternalEntities;
parser->m_freeInternalEntities = openEntity;
@@ -5990,29 +5971,19 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
return XML_ERROR_NONE;
}
-#ifdef XML_DTD
- if (entity->is_param) {
- int tok;
- parser->m_processor = prologProcessor;
- tok = XmlPrologTok(parser->m_encoding, s, end, &next);
- return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
- XML_ACCOUNT_DIRECT);
- } else
-#endif /* XML_DTD */
- {
- parser->m_processor = contentProcessor;
- /* see externalEntityContentProcessor vs contentProcessor */
- result = doContent(parser, parser->m_parentParser ? 1 : 0,
- parser->m_encoding, s, end, nextPtr,
- (XML_Bool)! parser->m_parsingStatus.finalBuffer,
- XML_ACCOUNT_DIRECT);
- if (result == XML_ERROR_NONE) {
- if (! storeRawNames(parser))
- return XML_ERROR_NO_MEMORY;
+ if (parser->m_openInternalEntities == NULL) {
+ parser->m_processor = entity->is_param ? prologProcessor : contentProcessor;
+ // internalEntityProcessor is called from callProcessor's while(1) loop,
+ // therefore "end" denotes callProcessor's "end", which denotes the end
+ // of the current buffer being parsed. Consequently, if we do not have
+ // any open entities left and have reached to the end, we must not
+ // trigger a reentry.
+ if (end == *nextPtr) {
+ return XML_ERROR_NONE;
}
- return result;
}
+ triggerReenter(parser);
+ return XML_ERROR_NONE;
}
static enum XML_Error PTRCALL
--
2.33.0

View File

@ -0,0 +1,89 @@
From 74308916d90218707bd7e8f61fbf52032e0e633d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
Date: Wed, 25 Sep 2024 09:34:48 +0200
Subject: [PATCH 4/7] Add next pointer to appendAttributeValue
This commits extends appendAttributeValue by introducing a new parameter
that will be set to the next token to process.
Having such a parameter allows us to reenter the function after an exit
and continue from the last token pointed by the pointer.
Reference: https://github.com/libexpat/libexpat/pull/973/commits/74308916d90218707bd7e8f61fbf52032e0e633d
Conflict: adapt appendAttributeValue
---
lib/xmlparse.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index cc5a609..781fc71 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -486,10 +486,10 @@ static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *,
XML_Bool isCdata, const char *,
const char *, STRING_POOL *,
enum XML_Account account);
-static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *,
- XML_Bool isCdata, const char *,
- const char *, STRING_POOL *,
- enum XML_Account account);
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
+ const char *ptr, const char *end, STRING_POOL *pool,
+ enum XML_Account account, const char **nextPtr);
static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end);
static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
@@ -5994,8 +5994,8 @@ static enum XML_Error
storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *ptr, const char *end, STRING_POOL *pool,
enum XML_Account account) {
- enum XML_Error result
- = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account);
+ enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end,
+ pool, account, NULL);
if (result)
return result;
if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
@@ -6008,7 +6008,7 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
static enum XML_Error
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *ptr, const char *end, STRING_POOL *pool,
- enum XML_Account account) {
+ enum XML_Account account, const char **nextPtr) {
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
#ifndef XML_DTD
UNUSED_P(account);
@@ -6026,6 +6026,9 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
#endif
switch (tok) {
case XML_TOK_NONE:
+ if (nextPtr) {
+ *nextPtr = next;
+ }
return XML_ERROR_NONE;
case XML_TOK_INVALID:
if (enc == parser->m_encoding)
@@ -6174,7 +6177,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
result = appendAttributeValue(parser, parser->m_internalEncoding,
isCdata, (const char *)entity->textPtr,
(const char *)textEnd, pool,
- XML_ACCOUNT_ENTITY_EXPANSION);
+ XML_ACCOUNT_ENTITY_EXPANSION, NULL);
#if defined(XML_DTD) || XML_GE == 1
entityTrackingOnClose(parser, entity, __LINE__);
#endif
@@ -6201,6 +6204,9 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
/* LCOV_EXCL_STOP */
}
ptr = next;
+ if (nextPtr) {
+ *nextPtr = next;
+ }
}
/* not reached */
}
--
2.33.0

View File

@ -0,0 +1,247 @@
From da10ca23282cf336553307dcc47dafb5b7378ad0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
Date: Tue, 27 Aug 2024 17:14:50 +0200
Subject: [PATCH 5/7] Break cyclic appendAttributeValue recursion
During processing attributes with entity references,
appendAttributeValue can reach high recursion depths that can lead to
a crash.
This commit switches the processing to an iterative approach similar to
the fix for internal entity processing. A new m_openAttributeEntities
list is introduced to keep track of entity references that need
processing. When a new entity reference is detected, instead of calling
appendAttributeValue recursively, the entity will be added to open
entities list and the execution will return to storeAttributeValue,
where newly added entity will be handled. After the entity processing
is done, appendAttributeValue will be called by using the next token.
Reference: https://github.com/libexpat/libexpat/pull/973/commits/da10ca23282cf336553307dcc47dafb5b7378ad0
Conflict: adapt appendAttributeValue
---
lib/xmlparse.c | 145 +++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 127 insertions(+), 18 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 781fc71..c86da91 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -457,6 +457,8 @@ static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
enum XML_Account account);
static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
XML_Bool betweenDecl);
+static enum XML_Error processAttributeEntity(XML_Parser parser, ENTITY *entity,
+ XML_Bool betweenDecl);
static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
const ENCODING *enc, const char *start,
const char *end, const char **endPtr,
@@ -665,6 +667,8 @@ struct XML_ParserStruct {
const char *m_positionPtr;
OPEN_INTERNAL_ENTITY *m_openInternalEntities;
OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
+ OPEN_INTERNAL_ENTITY *m_openAttributeEntities;
+ OPEN_INTERNAL_ENTITY *m_freeAttributeEntities;
XML_Bool m_defaultExpandInternalEntities;
int m_tagLevel;
ENTITY *m_declEntity;
@@ -1103,6 +1107,7 @@ parserCreate(const XML_Char *encodingName,
parser->m_freeBindingList = NULL;
parser->m_freeTagList = NULL;
parser->m_freeInternalEntities = NULL;
+ parser->m_freeAttributeEntities = NULL;
parser->m_groupSize = 0;
parser->m_groupConnector = NULL;
@@ -1204,6 +1209,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_eventEndPtr = NULL;
parser->m_positionPtr = NULL;
parser->m_openInternalEntities = NULL;
+ parser->m_openAttributeEntities = NULL;
parser->m_defaultExpandInternalEntities = XML_TRUE;
parser->m_tagLevel = 0;
parser->m_tagStack = NULL;
@@ -1275,6 +1281,15 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
openEntity->next = parser->m_freeInternalEntities;
parser->m_freeInternalEntities = openEntity;
}
+ /* move m_openAttributeEntities to m_freeAttributeEntities (i.e. same task but
+ * for attributes) */
+ openEntityList = parser->m_openAttributeEntities;
+ while (openEntityList) {
+ OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
+ openEntityList = openEntity->next;
+ openEntity->next = parser->m_freeAttributeEntities;
+ parser->m_freeAttributeEntities = openEntity;
+ }
moveToFreeBindingList(parser, parser->m_inheritedBindings);
FREE(parser, parser->m_unknownEncodingMem);
if (parser->m_unknownEncodingRelease)
@@ -1531,7 +1546,20 @@ XML_ParserFree(XML_Parser parser) {
entityList = entityList->next;
FREE(parser, openEntity);
}
-
+ /* free m_openAttributeEntities and m_freeAttributeEntities */
+ entityList = parser->m_openAttributeEntities;
+ for (;;) {
+ OPEN_INTERNAL_ENTITY *openEntity;
+ if (entityList == NULL) {
+ if (parser->m_freeAttributeEntities == NULL)
+ break;
+ entityList = parser->m_freeAttributeEntities;
+ parser->m_freeAttributeEntities = NULL;
+ }
+ openEntity = entityList;
+ entityList = entityList->next;
+ FREE(parser, openEntity);
+ }
destroyBindings(parser->m_freeBindingList, parser);
destroyBindings(parser->m_inheritedBindings, parser);
poolDestroy(&parser->m_tempPool);
@@ -5859,6 +5887,7 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
}
}
+/* KEEP IN SYNC with processAttributeEntity */
static enum XML_Error
processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
OPEN_INTERNAL_ENTITY *openEntity;
@@ -5890,6 +5919,37 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
return XML_ERROR_NONE;
}
+/* KEEP IN SYNC with processInternalEntity */
+static enum XML_Error
+processAttributeEntity(XML_Parser parser, ENTITY *entity,
+ XML_Bool betweenDecl) {
+ OPEN_INTERNAL_ENTITY *openEntity;
+
+ if (parser->m_freeAttributeEntities) {
+ openEntity = parser->m_freeAttributeEntities;
+ parser->m_freeAttributeEntities = openEntity->next;
+ } else {
+ openEntity
+ = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
+ if (! openEntity)
+ return XML_ERROR_NO_MEMORY;
+ }
+ entity->open = XML_TRUE;
+#if XML_GE == 1
+ entityTrackingOnOpen(parser, entity, __LINE__);
+#endif
+ entity->processed = 0;
+ openEntity->next = parser->m_openAttributeEntities;
+ parser->m_openAttributeEntities = openEntity;
+ openEntity->entity = entity;
+ openEntity->startTagLevel = parser->m_tagLevel;
+ openEntity->betweenDecl = betweenDecl;
+ openEntity->internalEventPtr = NULL;
+ openEntity->internalEventEndPtr = NULL;
+
+ return XML_ERROR_NONE;
+}
+
static enum XML_Error PTRCALL
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
@@ -5994,8 +6054,67 @@ static enum XML_Error
storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
const char *ptr, const char *end, STRING_POOL *pool,
enum XML_Account account) {
- enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end,
- pool, account, NULL);
+ const char *next = ptr;
+ enum XML_Error result = XML_ERROR_NONE;
+
+ while (1) {
+ if (! parser->m_openAttributeEntities) {
+ result = appendAttributeValue(parser, enc, isCdata, next, end, pool,
+ account, &next);
+ } else {
+ OPEN_INTERNAL_ENTITY *const openEntity = parser->m_openAttributeEntities;
+ if (! openEntity)
+ return XML_ERROR_UNEXPECTED_STATE;
+
+ ENTITY *const entity = openEntity->entity;
+ const char *const textStart
+ = ((const char *)entity->textPtr) + entity->processed;
+ const char *const textEnd
+ = (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);
+ 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
+ // will set the 'reenter' flag and return. Therefore openEntity is either
+ // the head or next to the new head.
+ if (parser->m_openAttributeEntities == openEntity) {
+ // No new entity detected during entity processing,
+ // openEntity is still the head.
+ parser->m_openAttributeEntities = parser->m_openAttributeEntities->next;
+ } else {
+ // New entity detected since list has a new head. openEntity is the
+ // second element.
+ parser->m_openAttributeEntities->next = openEntity->next;
+ }
+ /* put openEntity back in list of free instances */
+ openEntity->next = parser->m_freeAttributeEntities;
+ parser->m_freeAttributeEntities = openEntity;
+ }
+
+ // Break if an error occurred or there is nothing left to process
+ if (result || (parser->m_openAttributeEntities == NULL && end == next)) {
+ break;
+ }
+ }
+
if (result)
return result;
if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
@@ -6169,21 +6288,11 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
} else {
enum XML_Error result;
- const XML_Char *textEnd = entity->textPtr + entity->textLen;
- entity->open = XML_TRUE;
-#if defined(XML_DTD) || XML_GE == 1
- entityTrackingOnOpen(parser, entity, __LINE__);
-#endif
- result = appendAttributeValue(parser, parser->m_internalEncoding,
- isCdata, (const char *)entity->textPtr,
- (const char *)textEnd, pool,
- XML_ACCOUNT_ENTITY_EXPANSION, NULL);
-#if defined(XML_DTD) || XML_GE == 1
- entityTrackingOnClose(parser, entity, __LINE__);
-#endif
- entity->open = XML_FALSE;
- if (result)
- return result;
+ result = processAttributeEntity(parser, entity, XML_FALSE);
+ if (nextPtr) {
+ *nextPtr = next;
+ }
+ return result;
}
} break;
default:
--
2.33.0

View File

@ -0,0 +1,105 @@
From bf97ac508110dc390bd5471ed4904d5a4044332b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
Date: Mon, 7 Oct 2024 15:38:53 +0200
Subject: [PATCH 6/7] Add next pointer to storeEntityValue
This commit introduces a new nextPtr parameter to storeEntityValue.
After finishing its execution, storeEntityValue function sets this
parameter in way that it points to the next token to process.
This is useful when we want to leave and reenter storeEntityValue during
its execution since nextPtr will point where we left.
This commit is base to the following commit.
Reference: https://github.com/libexpat/libexpat/pull/973/commits/bf97ac508110dc390bd5471ed4904d5a4044332b
Conflict: NA
---
lib/xmlparse.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index c86da91..8f556d9 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -498,7 +498,8 @@ static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
#if XML_GE == 1
static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end,
- enum XML_Account account);
+ enum XML_Account account,
+ const char **nextPtr);
#else
static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity);
#endif
@@ -4594,7 +4595,7 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
}
/* found end of entity value - can store it now */
return storeEntityValue(parser, parser->m_encoding, s, end,
- XML_ACCOUNT_DIRECT);
+ XML_ACCOUNT_DIRECT, NULL);
} else if (tok == XML_TOK_XML_DECL) {
enum XML_Error result;
result = processXmlDecl(parser, 0, start, next);
@@ -4721,7 +4722,7 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end,
break;
}
/* found end of entity value - can store it now */
- return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT);
+ return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT, NULL);
}
start = next;
}
@@ -5166,7 +5167,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
// parser->m_declEntity->textPtr.
enum XML_Error result
= storeEntityValue(parser, enc, s + enc->minBytesPerChar,
- next - enc->minBytesPerChar, XML_ACCOUNT_NONE);
+ next - enc->minBytesPerChar, XML_ACCOUNT_NONE, NULL);
if (parser->m_declEntity) {
parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
parser->m_declEntity->textLen
@@ -6324,7 +6325,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
static enum XML_Error
storeEntityValue(XML_Parser parser, const ENCODING *enc,
const char *entityTextPtr, const char *entityTextEnd,
- enum XML_Account account) {
+ enum XML_Account account, const char **nextPtr) {
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
STRING_POOL *pool = &(dtd->entityValuePool);
enum XML_Error result = XML_ERROR_NONE;
@@ -6342,8 +6343,9 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
return XML_ERROR_NO_MEMORY;
}
+ const char *next;
for (;;) {
- const char *next
+ next
= entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
@@ -6412,7 +6414,7 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
result = storeEntityValue(
parser, parser->m_internalEncoding, (const char *)entity->textPtr,
(const char *)(entity->textPtr + entity->textLen),
- XML_ACCOUNT_ENTITY_EXPANSION);
+ XML_ACCOUNT_ENTITY_EXPANSION, NULL);
entityTrackingOnClose(parser, entity, __LINE__);
entity->open = XML_FALSE;
if (result)
@@ -6504,6 +6506,10 @@ endEntityValue:
# ifdef XML_DTD
parser->m_prologState.inEntityValue = oldInEntityValue;
# endif /* XML_DTD */
+ // If 'nextPtr' is given, it should be updated during the processing
+ if (nextPtr != NULL) {
+ *nextPtr = next;
+ }
return result;
}
--
2.33.0

View File

@ -0,0 +1,249 @@
From fabae41d28399e1d1623bde9ebd300c962e62ebe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
Date: Wed, 18 Sep 2024 13:52:06 +0200
Subject: [PATCH 7/7] Fix storeEntityValue recursion
Reference: https://github.com/libexpat/libexpat/pull/973/commits/fabae41d28399e1d1623bde9ebd300c962e62ebe
Conflict: adapt doProlog
---
lib/xmlparse.c | 153 ++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 140 insertions(+), 13 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 8f556d9..6c81713 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -459,6 +459,10 @@ static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
XML_Bool betweenDecl);
static enum XML_Error processAttributeEntity(XML_Parser parser, ENTITY *entity,
XML_Bool betweenDecl);
+#ifdef XML_DTD
+static enum XML_Error processValueEntity(XML_Parser parser, ENTITY *entity,
+ XML_Bool betweenDecl);
+#endif /* XML_DTD */
static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
const ENCODING *enc, const char *start,
const char *end, const char **endPtr,
@@ -500,6 +504,10 @@ static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
const char *start, const char *end,
enum XML_Account account,
const char **nextPtr);
+static enum XML_Error callStoreEntityValue(XML_Parser parser,
+ const ENCODING *enc,
+ const char *start, const char *end,
+ enum XML_Account account);
#else
static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity);
#endif
@@ -670,6 +678,8 @@ struct XML_ParserStruct {
OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
OPEN_INTERNAL_ENTITY *m_openAttributeEntities;
OPEN_INTERNAL_ENTITY *m_freeAttributeEntities;
+ OPEN_INTERNAL_ENTITY *m_openValueEntities;
+ OPEN_INTERNAL_ENTITY *m_freeValueEntities;
XML_Bool m_defaultExpandInternalEntities;
int m_tagLevel;
ENTITY *m_declEntity;
@@ -1109,6 +1119,7 @@ parserCreate(const XML_Char *encodingName,
parser->m_freeTagList = NULL;
parser->m_freeInternalEntities = NULL;
parser->m_freeAttributeEntities = NULL;
+ parser->m_freeValueEntities = NULL;
parser->m_groupSize = 0;
parser->m_groupConnector = NULL;
@@ -1211,6 +1222,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_positionPtr = NULL;
parser->m_openInternalEntities = NULL;
parser->m_openAttributeEntities = NULL;
+ parser->m_openValueEntities = NULL;
parser->m_defaultExpandInternalEntities = XML_TRUE;
parser->m_tagLevel = 0;
parser->m_tagStack = NULL;
@@ -1291,6 +1303,15 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
openEntity->next = parser->m_freeAttributeEntities;
parser->m_freeAttributeEntities = openEntity;
}
+ /* move m_openValueEntities to m_freeValueEntities (i.e. same task but
+ * for value entities) */
+ openEntityList = parser->m_openValueEntities;
+ while (openEntityList) {
+ OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
+ openEntityList = openEntity->next;
+ openEntity->next = parser->m_freeValueEntities;
+ parser->m_freeValueEntities = openEntity;
+ }
moveToFreeBindingList(parser, parser->m_inheritedBindings);
FREE(parser, parser->m_unknownEncodingMem);
if (parser->m_unknownEncodingRelease)
@@ -1561,6 +1582,20 @@ XML_ParserFree(XML_Parser parser) {
entityList = entityList->next;
FREE(parser, openEntity);
}
+ /* free m_openValueEntities and m_freeValueEntities */
+ entityList = parser->m_openValueEntities;
+ for (;;) {
+ OPEN_INTERNAL_ENTITY *openEntity;
+ if (entityList == NULL) {
+ if (parser->m_freeValueEntities == NULL)
+ break;
+ entityList = parser->m_freeValueEntities;
+ parser->m_freeValueEntities = NULL;
+ }
+ openEntity = entityList;
+ entityList = entityList->next;
+ FREE(parser, openEntity);
+ }
destroyBindings(parser->m_freeBindingList, parser);
destroyBindings(parser->m_inheritedBindings, parser);
poolDestroy(&parser->m_tempPool);
@@ -5165,9 +5200,9 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
#if defined(XML_DTD) || XML_GE == 1
// This will store the given replacement text in
// parser->m_declEntity->textPtr.
- enum XML_Error result
- = storeEntityValue(parser, enc, s + enc->minBytesPerChar,
- next - enc->minBytesPerChar, XML_ACCOUNT_NONE, NULL);
+ enum XML_Error result = callStoreEntityValue(
+ parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar,
+ XML_ACCOUNT_NONE);
if (parser->m_declEntity) {
parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
parser->m_declEntity->textLen
@@ -5951,6 +5986,38 @@ processAttributeEntity(XML_Parser parser, ENTITY *entity,
return XML_ERROR_NONE;
}
+/* KEEP IN SYNC with processInternalEntity */
+#ifdef XML_DTD
+static enum XML_Error
+processValueEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
+ OPEN_INTERNAL_ENTITY *openEntity;
+
+ if (parser->m_freeValueEntities) {
+ openEntity = parser->m_freeValueEntities;
+ parser->m_freeValueEntities = openEntity->next;
+ } else {
+ openEntity
+ = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
+ if (! openEntity)
+ return XML_ERROR_NO_MEMORY;
+ }
+ entity->open = XML_TRUE;
+# if XML_GE == 1
+ entityTrackingOnOpen(parser, entity, __LINE__);
+# endif
+ entity->processed = 0;
+ openEntity->next = parser->m_openValueEntities;
+ parser->m_openValueEntities = openEntity;
+ openEntity->entity = entity;
+ openEntity->startTagLevel = parser->m_tagLevel;
+ openEntity->betweenDecl = betweenDecl;
+ openEntity->internalEventPtr = NULL;
+ openEntity->internalEventEndPtr = NULL;
+
+ return XML_ERROR_NONE;
+}
+#endif /* XML_DTD */
+
static enum XML_Error PTRCALL
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
@@ -6409,16 +6476,8 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
} else
dtd->keepProcessing = dtd->standalone;
} else {
- entity->open = XML_TRUE;
- entityTrackingOnOpen(parser, entity, __LINE__);
- result = storeEntityValue(
- parser, parser->m_internalEncoding, (const char *)entity->textPtr,
- (const char *)(entity->textPtr + entity->textLen),
- XML_ACCOUNT_ENTITY_EXPANSION, NULL);
- entityTrackingOnClose(parser, entity, __LINE__);
- entity->open = XML_FALSE;
- if (result)
- goto endEntityValue;
+ result = processValueEntity(parser, entity, XML_FALSE);
+ goto endEntityValue;
}
break;
}
@@ -6513,6 +6572,74 @@ endEntityValue:
return result;
}
+static enum XML_Error
+callStoreEntityValue(XML_Parser parser, const ENCODING *enc,
+ const char *entityTextPtr, const char *entityTextEnd,
+ enum XML_Account account) {
+ const char *next = entityTextPtr;
+ enum XML_Error result = XML_ERROR_NONE;
+ while (1) {
+ if (! parser->m_openValueEntities) {
+ result
+ = storeEntityValue(parser, enc, next, entityTextEnd, account, &next);
+ } else {
+ OPEN_INTERNAL_ENTITY *const openEntity = parser->m_openValueEntities;
+ if (! openEntity)
+ return XML_ERROR_UNEXPECTED_STATE;
+
+ ENTITY *const entity = openEntity->entity;
+ const char *const textStart
+ = ((const char *)entity->textPtr) + entity->processed;
+ const char *const textEnd
+ = (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);
+ 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
+ // will set the 'reenter' flag and return. Therefore openEntity is either
+ // the head or next to the new head.
+ if (parser->m_openValueEntities == openEntity) {
+ // No new entity detected during entity processing,
+ // openEntity is still the head.
+ parser->m_openValueEntities = parser->m_openValueEntities->next;
+ } else {
+ // New entity detected since list has a new head. openEntity is the
+ // second element.
+ parser->m_openValueEntities->next = openEntity->next;
+ }
+ /* put openEntity back in list of free instances */
+ openEntity->next = parser->m_freeValueEntities;
+ parser->m_freeValueEntities = openEntity;
+ }
+
+ // Break if an error occurred or there is nothing left to process
+ if (result
+ || (parser->m_openValueEntities == NULL && entityTextEnd == next)) {
+ break;
+ }
+ }
+
+ return result;
+}
+
#else /* XML_GE == 0 */
static enum XML_Error
--
2.33.0

View File

@ -0,0 +1,229 @@
From 16a3b9d3566a95c4e502bfd008d05a0d015013ac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
Date: Wed, 9 Oct 2024 15:51:05 +0200
Subject: [PATCH 1/3] Merge entity processors
Reference: https://github.com/libexpat/libexpat/pull/973/commits/16a3b9d3566a95c4e502bfd008d05a0d015013ac
Conflict: adapt epilogProcessor
---
lib/xmlparse.c | 135 +++++++++++++++++++------------------------------
1 file changed, 51 insertions(+), 84 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 6c81713..9d8099e 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -389,6 +389,12 @@ typedef struct {
int *scaffIndex;
} DTD;
+enum EntityType {
+ ENTITY_INTERNAL,
+ ENTITY_ATTRIBUTE,
+ ENTITY_VALUE,
+};
+
typedef struct open_internal_entity {
const char *internalEventPtr;
const char *internalEventEndPtr;
@@ -396,6 +402,7 @@ typedef struct open_internal_entity {
ENTITY *entity;
int startTagLevel;
XML_Bool betweenDecl; /* WFC: PE Between Declarations */
+ enum EntityType type;
} OPEN_INTERNAL_ENTITY;
enum XML_Account {
@@ -455,14 +462,8 @@ static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
const char *next, const char **nextPtr,
XML_Bool haveMore, XML_Bool allowClosingDoctype,
enum XML_Account account);
-static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
- XML_Bool betweenDecl);
-static enum XML_Error processAttributeEntity(XML_Parser parser, ENTITY *entity,
- XML_Bool betweenDecl);
-#ifdef XML_DTD
-static enum XML_Error processValueEntity(XML_Parser parser, ENTITY *entity,
- XML_Bool betweenDecl);
-#endif /* XML_DTD */
+static enum XML_Error processEntity(XML_Parser parser, ENTITY *entity,
+ XML_Bool betweenDecl, enum EntityType type);
static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
const ENCODING *enc, const char *start,
const char *end, const char **endPtr,
@@ -3033,7 +3034,7 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
reportDefault(parser, enc, s, next);
break;
}
- result = processInternalEntity(parser, entity, XML_FALSE);
+ result = processEntity(parser, entity, XML_FALSE, ENTITY_INTERNAL);
if (result != XML_ERROR_NONE)
return result;
} else if (parser->m_externalEntityRefHandler) {
@@ -5627,7 +5628,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
enum XML_Error result;
XML_Bool betweenDecl
= (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
- result = processInternalEntity(parser, entity, betweenDecl);
+ result = processEntity(parser, entity, betweenDecl, ENTITY_INTERNAL);
if (result != XML_ERROR_NONE)
return result;
handleDefault = XML_FALSE;
@@ -5923,48 +5924,40 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
}
}
-/* KEEP IN SYNC with processAttributeEntity */
static enum XML_Error
-processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
- OPEN_INTERNAL_ENTITY *openEntity;
-
- if (parser->m_freeInternalEntities) {
- openEntity = parser->m_freeInternalEntities;
- parser->m_freeInternalEntities = openEntity->next;
- } else {
- openEntity
- = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
- if (! openEntity)
- return XML_ERROR_NO_MEMORY;
+processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl,
+ enum EntityType type) {
+ OPEN_INTERNAL_ENTITY *openEntity, **openEntityList, **freeEntityList;
+ switch (type) {
+ case ENTITY_INTERNAL:
+ parser->m_processor = internalEntityProcessor;
+ openEntityList = &parser->m_openInternalEntities;
+ freeEntityList = &parser->m_freeInternalEntities;
+ break;
+ case ENTITY_ATTRIBUTE:
+ openEntityList = &parser->m_openAttributeEntities;
+ freeEntityList = &parser->m_freeAttributeEntities;
+ break;
+ case ENTITY_VALUE:
+ openEntityList = &parser->m_openValueEntities;
+ freeEntityList = &parser->m_freeValueEntities;
+ break;
+ /* default case serves merely as a safety net in case of a
+ * wrong entityType. Therefore we exclude the following lines
+ * from the test coverage.
+ *
+ * LCOV_EXCL_START
+ */
+ default:
+ // Should not reach here
+ assert(0);
+ /* LCOV_EXCL_STOP */
}
- entity->open = XML_TRUE;
-#if defined(XML_DTD) || XML_GE == 1
- entityTrackingOnOpen(parser, entity, __LINE__);
-#endif
- entity->processed = 0;
- parser->m_processor = internalEntityProcessor;
- openEntity->next = parser->m_openInternalEntities;
- parser->m_openInternalEntities = openEntity;
- openEntity->entity = entity;
- openEntity->startTagLevel = parser->m_tagLevel;
- openEntity->betweenDecl = betweenDecl;
- openEntity->internalEventPtr = NULL;
- openEntity->internalEventEndPtr = NULL;
-
- triggerReenter(parser);
- return XML_ERROR_NONE;
-}
-
-/* KEEP IN SYNC with processInternalEntity */
-static enum XML_Error
-processAttributeEntity(XML_Parser parser, ENTITY *entity,
- XML_Bool betweenDecl) {
- OPEN_INTERNAL_ENTITY *openEntity;
- if (parser->m_freeAttributeEntities) {
- openEntity = parser->m_freeAttributeEntities;
- parser->m_freeAttributeEntities = openEntity->next;
- } else {
+ if (*freeEntityList) {
+ openEntity = *freeEntityList;
+ *freeEntityList = openEntity->next;
+ } else {
openEntity
= (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
if (! openEntity)
@@ -5975,48 +5968,22 @@ processAttributeEntity(XML_Parser parser, ENTITY *entity,
entityTrackingOnOpen(parser, entity, __LINE__);
#endif
entity->processed = 0;
- openEntity->next = parser->m_openAttributeEntities;
- parser->m_openAttributeEntities = openEntity;
+ openEntity->next = *openEntityList;
+ *openEntityList = openEntity;
openEntity->entity = entity;
+ openEntity->type = type;
openEntity->startTagLevel = parser->m_tagLevel;
openEntity->betweenDecl = betweenDecl;
openEntity->internalEventPtr = NULL;
openEntity->internalEventEndPtr = NULL;
- return XML_ERROR_NONE;
-}
-
-/* KEEP IN SYNC with processInternalEntity */
-#ifdef XML_DTD
-static enum XML_Error
-processValueEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
- OPEN_INTERNAL_ENTITY *openEntity;
-
- if (parser->m_freeValueEntities) {
- openEntity = parser->m_freeValueEntities;
- parser->m_freeValueEntities = openEntity->next;
- } else {
- openEntity
- = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
- if (! openEntity)
- return XML_ERROR_NO_MEMORY;
+ // Only internal entities make use of the reenter flag
+ // therefore no need to set it for other entity types
+ if (type == ENTITY_INTERNAL) {
+ triggerReenter(parser);
}
- entity->open = XML_TRUE;
-# if XML_GE == 1
- entityTrackingOnOpen(parser, entity, __LINE__);
-# endif
- entity->processed = 0;
- openEntity->next = parser->m_openValueEntities;
- parser->m_openValueEntities = openEntity;
- openEntity->entity = entity;
- openEntity->startTagLevel = parser->m_tagLevel;
- openEntity->betweenDecl = betweenDecl;
- openEntity->internalEventPtr = NULL;
- openEntity->internalEventEndPtr = NULL;
-
return XML_ERROR_NONE;
}
-#endif /* XML_DTD */
static enum XML_Error PTRCALL
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
@@ -6356,7 +6323,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
} else {
enum XML_Error result;
- result = processAttributeEntity(parser, entity, XML_FALSE);
+ result = processEntity(parser, entity, XML_FALSE, ENTITY_ATTRIBUTE);
if (nextPtr) {
*nextPtr = next;
}
@@ -6476,7 +6443,7 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
} else
dtd->keepProcessing = dtd->standalone;
} else {
- result = processValueEntity(parser, entity, XML_FALSE);
+ result = processEntity(parser, entity, XML_FALSE, ENTITY_VALUE);
goto endEntityValue;
}
break;
--
2.33.0

View File

@ -0,0 +1,199 @@
From 08ff7591ffe9519f627e246f841427c6f10edc2a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
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

View File

@ -0,0 +1,133 @@
From 4d0be4b56cf61428ccb17fbf9953a39defb77282 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
Date: Sat, 23 Nov 2024 21:37:15 +0100
Subject: [PATCH] Fix infinite loop with indirectly recursive entities
Detection of recursive entity references are currently failing because
we process and close entities before their inner references are
processed. Since the detection works by checking wheter the referenced
entity is already open, this early close leads to wrong results. This
commit delays closing entities until their inner entities are processed
and closed. This is achieved by postponing the unsetting of the open
flag and using a new hasMore flag to check if the entity has more
elements to process.
Reference: https://github.com/libexpat/libexpat/pull/973/commits/495fb53b16d510dd0d0307fef2145437a7ad6ab1
Conflict: adapt internalEntityProcessor
---
lib/xmlparse.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 325d5e7..bad6aae 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -303,6 +303,10 @@ typedef struct {
const XML_Char *publicId;
const XML_Char *notation;
XML_Bool open;
+ XML_Bool hasMore; /* true if entity has not been completely processed */
+ /* An entity can be open while being already completely processed (hasMore ==
+ XML_FALSE). The reason is the delayed closing of entities until their inner
+ entities are processed and closed */
XML_Bool is_param;
XML_Bool is_internal; /* true if declared in internal subset outside PE */
} ENTITY;
@@ -5970,6 +5974,7 @@ processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl,
return XML_ERROR_NO_MEMORY;
}
entity->open = XML_TRUE;
+ entity->hasMore = XML_TRUE;
#if XML_GE == 1
entityTrackingOnOpen(parser, entity, __LINE__);
#endif
@@ -6004,7 +6009,7 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
return XML_ERROR_UNEXPECTED_STATE;
entity = openEntity->entity;
- if (entity->open) {
+ if (entity->hasMore) {
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 */
@@ -6036,7 +6041,10 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
return result;
}
- entity->open = XML_FALSE;
+ // Entity is complete. We cannot close it here since we need to first
+ // process its possible inner entities (which are added to the
+ // m_openInternalEntities during doProlog or doContent calls above)
+ entity->hasMore = XML_FALSE;
triggerReenter(parser);
return result;
}
@@ -6044,6 +6052,7 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
#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
@@ -6108,7 +6117,7 @@ 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;
- if (entity->open) {
+ if (entity->hasMore) {
result = appendAttributeValue(
parser, parser->m_internalEncoding, isCdata, textStart, textEnd,
pool, XML_ACCOUNT_ENTITY_EXPANSION, &nextInEntity);
@@ -6123,7 +6132,10 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
continue;
}
- entity->open = XML_FALSE;
+ // Entity is complete. We cannot close it here since we need to first
+ // process its possible inner entities (which are added to the
+ // m_openAttributeEntities during appendAttributeValue)
+ entity->hasMore = XML_FALSE;
triggerReenter(parser);
continue;
}
@@ -6131,6 +6143,7 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
#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
@@ -6567,7 +6580,7 @@ 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;
- if (entity->open) {
+ if (entity->hasMore) {
result = storeEntityValue(parser, parser->m_internalEncoding, textStart,
textEnd, XML_ACCOUNT_ENTITY_EXPANSION,
&nextInEntity);
@@ -6582,7 +6595,10 @@ callStoreEntityValue(XML_Parser parser, const ENCODING *enc,
continue;
}
- entity->open = XML_FALSE;
+ // Entity is complete. We cannot close it here since we need to first
+ // process its possible inner entities (which are added to the
+ // m_openValueEntities during storeEntityValue)
+ entity->hasMore = XML_FALSE;
triggerReenter(parser);
continue;
}
@@ -6590,6 +6606,7 @@ callStoreEntityValue(XML_Parser parser, const ENCODING *enc,
# 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

View File

@ -0,0 +1,53 @@
From f2edeaaecebfad1edef3e6504ffb772e5e4dd089 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
Date: Wed, 5 Mar 2025 12:33:47 +0100
Subject: [PATCH] Delete the check that prevents reentry
The early return in case of zero open internal entities and matching
end/nextPtr pointers cause the parser to miss XML_ERROR_NO_ELEMENTS
error.
The reason is that the internalEntityProcessor does not set the
m_reenter flag in such a case, which results in skipping the
prologProcessor or contentProcessor depending on wheter is_param is set
or not. However, this last skipped call to mentioned processors can
detect the non-existence of elements when some are expected.
Reference: https://github.com/libexpat/libexpat/pull/973/commits/f2edeaaecebfad1edef3e6504ffb772e5e4dd089
Conflict: NA
---
lib/xmlparse.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index d5161e93..de459192 100644
--- a/lib/xmlparse.c
+++ b/ib/xmlparse.c
@@ -6034,6 +6034,8 @@ static enum XML_Error PTRCALL
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
UNUSED_P(s);
+ UNUSED_P(end);
+ UNUSED_P(nextPtr);
ENTITY *entity;
const char *textStart, *textEnd;
const char *next;
@@ -6101,14 +6103,6 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
if (parser->m_openInternalEntities == NULL) {
parser->m_processor = entity->is_param ? prologProcessor : contentProcessor;
- // internalEntityProcessor is called from callProcessor's while(1) loop,
- // therefore "end" denotes callProcessor's "end", which denotes the end
- // of the current buffer being parsed. Consequently, if we do not have
- // any open entities left and have reached to the end, we must not
- // trigger a reentry.
- if (end == *nextPtr) {
- return XML_ERROR_NONE;
- }
}
triggerReenter(parser);
return XML_ERROR_NONE;
--
2.33.0

View File

@ -1,7 +1,7 @@
%define Rversion %(echo %{version} | sed -e 's/\\./_/g' -e 's/^/R_/')
Name: expat
Version: 2.5.0
Release: 7
Release: 8
Summary: An XML parser library
License: MIT
URL: https://libexpat.github.io/
@ -31,6 +31,17 @@ Patch21: backport-CVE-2024-45491.patch
Patch22: backport-CVE-2024-45492.patch
Patch23: backport-CVE-2024-50602.patch
Patch24: backport-CVE-2024-50602-testcase.patch
Patch25: backport-001-CVE-2024-8176.patch
Patch26: backport-002-CVE-2024-8176.patch
Patch27: backport-003-CVE-2024-8176.patch
Patch28: backport-004-CVE-2024-8176.patch
Patch29: backport-005-CVE-2024-8176.patch
Patch30: backport-006-CVE-2024-8176.patch
Patch31: backport-007-CVE-2024-8176.patch
Patch32: backport-008-CVE-2024-8176.patch
Patch33: backport-009-CVE-2024-8176.patch
Patch34: backport-010-CVE-2024-8176.patch
Patch35: backport-011-CVE-2024-8176.patch
BuildRequires: sed,autoconf,automake,gcc-c++,libtool,xmlto
@ -79,6 +90,9 @@ find %{buildroot} -type f -name changelog -delete
%{_mandir}/man1/*
%changelog
* Fri Mar 28 2025 zhuofeng <1107893276@qq.com> - 2.5.0-8
- fix CVE-2024-8176
* Tue Oct 29 2024 liningjie <liningjie@xfusion.com> - 2.5.0-7
- add testcase for CVE-2024-50602