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 "&amp;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 "&amp;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;
 
openSUSE Build Service is sponsored by