File expat-CVE-2026-24515.patch of Package expat.42557

From 86fc914a7acc49246d5fde0ab6ed97eb8a0f15f9 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Sun, 18 Jan 2026 17:53:37 +0100
Subject: [PATCH 1/3] lib: Make XML_ExternalEntityParserCreate copy unknown
 encoding handler user data

Patch suggested by Artiphishell Inc.
---
 lib/xmlparse.c | 3 +++
 1 file changed, 3 insertions(+)

Index: expat-2.7.1/lib/xmlparse.c
===================================================================
--- expat-2.7.1.orig/lib/xmlparse.c
+++ expat-2.7.1/lib/xmlparse.c
@@ -1743,6 +1743,7 @@ XML_ExternalEntityParserCreate(XML_Parse
   XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
   XML_SkippedEntityHandler oldSkippedEntityHandler;
   XML_UnknownEncodingHandler oldUnknownEncodingHandler;
+  void *oldUnknownEncodingHandlerData;
   XML_ElementDeclHandler oldElementDeclHandler;
   XML_AttlistDeclHandler oldAttlistDeclHandler;
   XML_EntityDeclHandler oldEntityDeclHandler;
@@ -1788,6 +1789,7 @@ XML_ExternalEntityParserCreate(XML_Parse
   oldExternalEntityRefHandler = parser->m_externalEntityRefHandler;
   oldSkippedEntityHandler = parser->m_skippedEntityHandler;
   oldUnknownEncodingHandler = parser->m_unknownEncodingHandler;
+  oldUnknownEncodingHandlerData = parser->m_unknownEncodingHandlerData;
   oldElementDeclHandler = parser->m_elementDeclHandler;
   oldAttlistDeclHandler = parser->m_attlistDeclHandler;
   oldEntityDeclHandler = parser->m_entityDeclHandler;
@@ -1848,6 +1850,7 @@ XML_ExternalEntityParserCreate(XML_Parse
   parser->m_externalEntityRefHandler = oldExternalEntityRefHandler;
   parser->m_skippedEntityHandler = oldSkippedEntityHandler;
   parser->m_unknownEncodingHandler = oldUnknownEncodingHandler;
+  parser->m_unknownEncodingHandlerData = oldUnknownEncodingHandlerData;
   parser->m_elementDeclHandler = oldElementDeclHandler;
   parser->m_attlistDeclHandler = oldAttlistDeclHandler;
   parser->m_entityDeclHandler = oldEntityDeclHandler;
Index: expat-2.7.1/tests/basic_tests.c
===================================================================
--- expat-2.7.1.orig/tests/basic_tests.c
+++ expat-2.7.1/tests/basic_tests.c
@@ -4570,6 +4570,46 @@ START_TEST(test_unknown_encoding_invalid
 }
 END_TEST
 
+START_TEST(test_unknown_encoding_user_data_primary) {
+  // This test is based on ideas contributed by Artiphishell Inc.
+  const char *const text = "<?xml version='1.0' encoding='x-unk'?>\n"
+                           "<root />\n";
+  XML_Parser parser = XML_ParserCreate(NULL);
+  XML_SetUnknownEncodingHandler(parser,
+                                user_data_checking_unknown_encoding_handler,
+                                (void *)(intptr_t)0xC0FFEE);
+
+  assert_true(_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
+              == XML_STATUS_OK);
+
+  XML_ParserFree(parser);
+}
+END_TEST
+
+START_TEST(test_unknown_encoding_user_data_secondary) {
+  // This test is based on ideas contributed by Artiphishell Inc.
+  const char *const text_main = "<!DOCTYPE r [\n"
+                                "  <!ENTITY ext SYSTEM 'ext.ent'>\n"
+                                "]>\n"
+                                "<r>&ext;</r>\n";
+  const char *const text_external = "<?xml version='1.0' encoding='x-unk'?>\n"
+                                    "<e>data</e>";
+  ExtTest2 test_data = {text_external, (int)strlen(text_external), NULL, NULL};
+  XML_Parser parser = XML_ParserCreate(NULL);
+  XML_SetExternalEntityRefHandler(parser, external_entity_loader2);
+  XML_SetUnknownEncodingHandler(parser,
+                                user_data_checking_unknown_encoding_handler,
+                                (void *)(intptr_t)0xC0FFEE);
+  XML_SetUserData(parser, &test_data);
+
+  assert_true(_XML_Parse_SINGLE_BYTES(parser, text_main, (int)strlen(text_main),
+                                      XML_TRUE)
+              == XML_STATUS_OK);
+
+  XML_ParserFree(parser);
+}
+END_TEST
+
 /* Test an external entity parser set to use latin-1 detects UTF-16
  * BOMs correctly.
  */
@@ -6416,6 +6456,8 @@ make_basic_test_case(Suite *s) {
   tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
   tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
   tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
+  tcase_add_test(tc_basic, test_unknown_encoding_user_data_primary);
+  tcase_add_test(tc_basic, test_unknown_encoding_user_data_secondary);
   tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16le_bom);
   tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16be_bom);
   tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16le_bom2);
Index: expat-2.7.1/tests/handlers.c
===================================================================
--- expat-2.7.1.orig/tests/handlers.c
+++ expat-2.7.1/tests/handlers.c
@@ -45,6 +45,7 @@
 #  undef NDEBUG /* because test suite relies on assert(...) at the moment */
 #endif
 
+#include <stdint.h>
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
@@ -407,6 +408,15 @@ long_encoding_handler(void *userData, co
   return XML_STATUS_OK;
 }
 
+int XMLCALL
+user_data_checking_unknown_encoding_handler(void *userData,
+                                            const XML_Char *encoding,
+                                            XML_Encoding *info) {
+  const intptr_t number = (intptr_t)userData;
+  assert_true(number == 0xC0FFEE);
+  return long_encoding_handler(userData, encoding, info);
+}
+
 /* External Entity Handlers */
 
 int XMLCALL
Index: expat-2.7.1/tests/handlers.h
===================================================================
--- expat-2.7.1.orig/tests/handlers.h
+++ expat-2.7.1/tests/handlers.h
@@ -159,6 +159,9 @@ extern int XMLCALL long_encoding_handler
                                          const XML_Char *encoding,
                                          XML_Encoding *info);
 
+extern int XMLCALL user_data_checking_unknown_encoding_handler(
+    void *userData, const XML_Char *encoding, XML_Encoding *info);
+
 /* External Entity Handlers */
 
 typedef struct ExtOption {
openSUSE Build Service is sponsored by