File expat-CVE-2023-52425-backport-parser-changes.patch of Package expat.36379
From: Simon Lees <sflees@suse.de>
Date: Fri, Mar 1 10:42:13
Subject: CVE-2023-52425 Additional parser fixes
In order for the backport of CVE-2023-52425 to pass the testsuite
some additional changes needed to be backported to xmlparse.c
===
Index: expat-2.4.4/lib/xmlparse.c
===================================================================
--- expat-2.4.4.orig/lib/xmlparse.c
+++ expat-2.4.4/lib/xmlparse.c
@@ -60,10 +60,12 @@
#include <expat_config.h>
-#if ! defined(_GNU_SOURCE)
-# define _GNU_SOURCE 1 /* syscall prototype */
+#if ! defined(XML_CONTEXT_BYTES) || (1 - XML_CONTEXT_BYTES - 1 == 2) \
+ || (XML_CONTEXT_BYTES + 0 < 0)
+# error XML_CONTEXT_BYTES must be defined, non-empty and >=0 (0 to disable, >=1 to enable; 1024 is a common default)
#endif
+
#ifdef _WIN32
/* force stdlib to define rand_s() */
# if ! defined(_CRT_RAND_S)
@@ -590,7 +592,6 @@ static XML_Parser getRootParserOf(XML_Pa
static unsigned long getDebugLevel(const char *variableName,
unsigned long defaultDebugLevel);
-
#define poolStart(pool) ((pool)->start)
#define poolEnd(pool) ((pool)->ptr)
#define poolLength(pool) ((pool)->ptr - (pool)->start)
@@ -3041,9 +3042,6 @@ doContent(XML_Parser parser, int startTa
int len;
const char *rawName;
TAG *tag = parser->m_tagStack;
- parser->m_tagStack = tag->parent;
- tag->parent = parser->m_freeTagList;
- parser->m_freeTagList = tag;
rawName = s + enc->minBytesPerChar * 2;
len = XmlNameLength(enc, rawName);
if (len != tag->rawNameLength
@@ -3051,6 +3049,9 @@ doContent(XML_Parser parser, int startTa
*eventPP = rawName;
return XML_ERROR_TAG_MISMATCH;
}
+ parser->m_tagStack = tag->parent;
+ tag->parent = parser->m_freeTagList;
+ parser->m_freeTagList = tag;
--parser->m_tagLevel;
if (parser->m_endElementHandler) {
const XML_Char *localPart;
@@ -4508,8 +4509,7 @@ entityValueInitProcessor(XML_Parser pars
then, when this routine is entered the next time, XmlPrologTok will
return XML_TOK_INVALID, since the BOM is still in the buffer
*/
- else if (tok == XML_TOK_BOM && next == end
- && ! parser->m_parsingStatus.finalBuffer) {
+ else if (tok == XML_TOK_BOM) {
# ifdef XML_DTD
if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
XML_ACCOUNT_DIRECT)) {
@@ -4519,7 +4519,7 @@ entityValueInitProcessor(XML_Parser pars
# endif
*nextPtr = next;
- return XML_ERROR_NONE;
+ s = next;
}
/* If we get this token, we have the start of what might be a
normal tag, but not a declaration (i.e. it doesn't begin with
@@ -5003,10 +5003,10 @@ doProlog(XML_Parser parser, const ENCODI
parser->m_handlerArg, parser->m_declElementType->name,
parser->m_declAttributeId->name, parser->m_declAttributeType, 0,
role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
- poolClear(&parser->m_tempPool);
handleDefault = XML_FALSE;
}
}
+ poolClear(&parser->m_tempPool);
break;
case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
@@ -5048,6 +5048,9 @@ doProlog(XML_Parser parser, const ENCODI
break;
case XML_ROLE_ENTITY_VALUE:
if (dtd->keepProcessing) {
+#ifdef XML_DTD
+ // 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);
@@ -5068,6 +5071,25 @@ doProlog(XML_Parser parser, const ENCODI
poolDiscard(&dtd->entityValuePool);
if (result != XML_ERROR_NONE)
return result;
+#else
+ // This will store "&entity123;" in parser->m_declEntity->textPtr
+ // to end up as "&entity123;" in the handler.
+ if (parser->m_declEntity != NULL) {
+ const enum XML_Error result
+ = storeSelfEntityValue(parser, parser->m_declEntity);
+ if (result != XML_ERROR_NONE)
+ return result;
+
+ if (parser->m_entityDeclHandler) {
+ *eventEndPP = s;
+ parser->m_entityDeclHandler(
+ parser->m_handlerArg, parser->m_declEntity->name,
+ parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
+ parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
+ handleDefault = XML_FALSE;
+ }
+ }
+#endif
}
break;
case XML_ROLE_DOCTYPE_SYSTEM_ID:
@@ -5126,6 +5148,16 @@ doProlog(XML_Parser parser, const ENCODI
}
break;
case XML_ROLE_ENTITY_COMPLETE:
+#ifndef XML_DTD
+ // This will store "&entity123;" in entity->textPtr
+ // to end up as "&entity123;" in the handler.
+ if (parser->m_declEntity != NULL) {
+ const enum XML_Error result
+ = storeSelfEntityValue(parser, parser->m_declEntity);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+#endif
if (dtd->keepProcessing && parser->m_declEntity
&& parser->m_entityDeclHandler) {
*eventEndPP = s;
@@ -5839,6 +5871,14 @@ internalEntityProcessor(XML_Parser parse
/* put openEntity back in list of free instances */
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 (parser->m_openInternalEntities != NULL
+ && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
+ return XML_ERROR_NONE;
}
#ifdef XML_DTD
@@ -6641,6 +6681,10 @@ getContext(XML_Parser parser) {
static XML_Bool
setContext(XML_Parser parser, const XML_Char *context) {
+ if (context == NULL) {
+ return XML_FALSE;
+ }
+
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
const XML_Char *s = context;