File expat-CVE-2026-32777.patch of Package expat.43408

From 55cda8c7125986e17d7e1825cba413bd94a35d02 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Sun, 1 Mar 2026 20:16:13 +0100
Subject: [PATCH 1/2] lib: Reject XML_TOK_INSTANCE_START infinite loop in
 entityValueProcessor

.. that OSS-Fuzz/ClusterFuzz uncovered
---
 expat/lib/xmlparse.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

Index: expat-2.7.1/lib/xmlparse.c
===================================================================
--- expat-2.7.1.orig/lib/xmlparse.c
+++ expat-2.7.1/lib/xmlparse.c
@@ -5073,7 +5073,7 @@ entityValueInitProcessor(XML_Parser pars
     }
     /* 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
-       "<!").  In a DTD context, that isn't legal.
+       "<!" or "<?").  In a DTD context, that isn't legal.
     */
     else if (tok == XML_TOK_INSTANCE_START) {
       *nextPtr = next;
@@ -5162,6 +5162,15 @@ entityValueProcessor(XML_Parser parser,
       /* found end of entity value - can store it now */
       return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT, NULL);
     }
+    /* 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
+       "<!" or "<?").  In a DTD context, that isn't legal.
+    */
+    else if (tok == XML_TOK_INSTANCE_START) {
+      *nextPtr = next;
+      return XML_ERROR_SYNTAX;
+    }
+
     start = next;
   }
 }
Index: expat-2.7.1/tests/misc_tests.c
===================================================================
--- expat-2.7.1.orig/tests/misc_tests.c
+++ expat-2.7.1/tests/misc_tests.c
@@ -679,6 +679,35 @@ START_TEST(test_misc_expected_event_ptr_
 }
 END_TEST
 
+START_TEST(test_misc_no_infinite_loop_issue_1161) {
+  XML_Parser parser = XML_ParserCreate(NULL);
+
+  const char *text = "<!DOCTYPE d SYSTEM 'secondary.txt'>";
+
+  struct ExtOption options[] = {
+      {XCS("secondary.txt"),
+       "<!ENTITY % p SYSTEM 'tertiary.txt'><!ENTITY g '%p;'>"},
+      {XCS("tertiary.txt"), "<?xml version='1.0'?><a"},
+      {NULL, NULL},
+  };
+
+  XML_SetUserData(parser, options);
+  XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
+  XML_SetExternalEntityRefHandler(parser, external_entity_optioner);
+
+  assert_true(_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
+              == XML_STATUS_ERROR);
+
+#if defined(XML_DTD)
+  assert_true(XML_GetErrorCode(parser) == XML_ERROR_EXTERNAL_ENTITY_HANDLING);
+#else
+  assert_true(XML_GetErrorCode(parser) == XML_ERROR_NO_ELEMENTS);
+#endif
+
+  XML_ParserFree(parser);
+}
+END_TEST
+
 void
 make_miscellaneous_test_case(Suite *s) {
   TCase *tc_misc = tcase_create("miscellaneous tests");
@@ -707,4 +736,5 @@ make_miscellaneous_test_case(Suite *s) {
   tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
   tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content);
   tcase_add_test(tc_misc, test_misc_expected_event_ptr_issue_980);
+  tcase_add_test(tc_misc, test_misc_no_infinite_loop_issue_1161);
 }
openSUSE Build Service is sponsored by