|
| 1 | +From efe0d86b3853b1636bd6c7f01bba3c6996c7b484 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Sebastian Pipping <sebastian@pipping.org> |
| 3 | +Date: Sun, 18 Jan 2026 17:53:37 +0100 |
| 4 | +Subject: [PATCH 1/3] lib: Make XML_ExternalEntityParserCreate copy unknown |
| 5 | + encoding handler user data |
| 6 | + |
| 7 | +Patch suggested by Artiphishell Inc. |
| 8 | +--- |
| 9 | + lib/xmlparse.c | 3 +++ |
| 10 | + 1 file changed, 3 insertions(+) |
| 11 | + |
| 12 | +diff --git a/lib/xmlparse.c b/lib/xmlparse.c |
| 13 | +index e2847b1..d804753 100644 |
| 14 | +--- a/lib/xmlparse.c |
| 15 | ++++ b/lib/xmlparse.c |
| 16 | +@@ -1742,6 +1742,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, |
| 17 | + XML_ExternalEntityRefHandler oldExternalEntityRefHandler; |
| 18 | + XML_SkippedEntityHandler oldSkippedEntityHandler; |
| 19 | + XML_UnknownEncodingHandler oldUnknownEncodingHandler; |
| 20 | ++ void *oldUnknownEncodingHandlerData; |
| 21 | + XML_ElementDeclHandler oldElementDeclHandler; |
| 22 | + XML_AttlistDeclHandler oldAttlistDeclHandler; |
| 23 | + XML_EntityDeclHandler oldEntityDeclHandler; |
| 24 | +@@ -1787,6 +1788,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, |
| 25 | + oldExternalEntityRefHandler = parser->m_externalEntityRefHandler; |
| 26 | + oldSkippedEntityHandler = parser->m_skippedEntityHandler; |
| 27 | + oldUnknownEncodingHandler = parser->m_unknownEncodingHandler; |
| 28 | ++ oldUnknownEncodingHandlerData = parser->m_unknownEncodingHandlerData; |
| 29 | + oldElementDeclHandler = parser->m_elementDeclHandler; |
| 30 | + oldAttlistDeclHandler = parser->m_attlistDeclHandler; |
| 31 | + oldEntityDeclHandler = parser->m_entityDeclHandler; |
| 32 | +@@ -1847,6 +1849,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, |
| 33 | + parser->m_externalEntityRefHandler = oldExternalEntityRefHandler; |
| 34 | + parser->m_skippedEntityHandler = oldSkippedEntityHandler; |
| 35 | + parser->m_unknownEncodingHandler = oldUnknownEncodingHandler; |
| 36 | ++ parser->m_unknownEncodingHandlerData = oldUnknownEncodingHandlerData; |
| 37 | + parser->m_elementDeclHandler = oldElementDeclHandler; |
| 38 | + parser->m_attlistDeclHandler = oldAttlistDeclHandler; |
| 39 | + parser->m_entityDeclHandler = oldEntityDeclHandler; |
| 40 | +-- |
| 41 | +2.45.4 |
| 42 | + |
| 43 | + |
| 44 | +From b973035150fadb162df899e2e0ac7fcfb6aafd2a Mon Sep 17 00:00:00 2001 |
| 45 | +From: Sebastian Pipping <sebastian@pipping.org> |
| 46 | +Date: Sun, 18 Jan 2026 17:26:31 +0100 |
| 47 | +Subject: [PATCH 2/3] tests: Cover effect of XML_SetUnknownEncodingHandler user |
| 48 | + data |
| 49 | + |
| 50 | +--- |
| 51 | + tests/basic_tests.c | 42 ++++++++++++++++++++++++++++++++++++++++++ |
| 52 | + tests/handlers.c | 10 ++++++++++ |
| 53 | + tests/handlers.h | 3 +++ |
| 54 | + 3 files changed, 55 insertions(+) |
| 55 | + |
| 56 | +diff --git a/tests/basic_tests.c b/tests/basic_tests.c |
| 57 | +index da5c0d4..2db2a76 100644 |
| 58 | +--- a/tests/basic_tests.c |
| 59 | ++++ b/tests/basic_tests.c |
| 60 | +@@ -4440,6 +4440,46 @@ START_TEST(test_unknown_encoding_invalid_attr_value) { |
| 61 | + } |
| 62 | + END_TEST |
| 63 | + |
| 64 | ++START_TEST(test_unknown_encoding_user_data_primary) { |
| 65 | ++ // This test is based on ideas contributed by Artiphishell Inc. |
| 66 | ++ const char *const text = "<?xml version='1.0' encoding='x-unk'?>\n" |
| 67 | ++ "<root />\n"; |
| 68 | ++ XML_Parser parser = XML_ParserCreate(NULL); |
| 69 | ++ XML_SetUnknownEncodingHandler(parser, |
| 70 | ++ user_data_checking_unknown_encoding_handler, |
| 71 | ++ (void *)(intptr_t)0xC0FFEE); |
| 72 | ++ |
| 73 | ++ assert_true(_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) |
| 74 | ++ == XML_STATUS_OK); |
| 75 | ++ |
| 76 | ++ XML_ParserFree(parser); |
| 77 | ++} |
| 78 | ++END_TEST |
| 79 | ++ |
| 80 | ++START_TEST(test_unknown_encoding_user_data_secondary) { |
| 81 | ++ // This test is based on ideas contributed by Artiphishell Inc. |
| 82 | ++ const char *const text_main = "<!DOCTYPE r [\n" |
| 83 | ++ " <!ENTITY ext SYSTEM 'ext.ent'>\n" |
| 84 | ++ "]>\n" |
| 85 | ++ "<r>&ext;</r>\n"; |
| 86 | ++ const char *const text_external = "<?xml version='1.0' encoding='x-unk'?>\n" |
| 87 | ++ "<e>data</e>"; |
| 88 | ++ ExtTest2 test_data = {text_external, (int)strlen(text_external), NULL, NULL}; |
| 89 | ++ XML_Parser parser = XML_ParserCreate(NULL); |
| 90 | ++ XML_SetExternalEntityRefHandler(parser, external_entity_loader2); |
| 91 | ++ XML_SetUnknownEncodingHandler(parser, |
| 92 | ++ user_data_checking_unknown_encoding_handler, |
| 93 | ++ (void *)(intptr_t)0xC0FFEE); |
| 94 | ++ XML_SetUserData(parser, &test_data); |
| 95 | ++ |
| 96 | ++ assert_true(_XML_Parse_SINGLE_BYTES(parser, text_main, (int)strlen(text_main), |
| 97 | ++ XML_TRUE) |
| 98 | ++ == XML_STATUS_OK); |
| 99 | ++ |
| 100 | ++ XML_ParserFree(parser); |
| 101 | ++} |
| 102 | ++END_TEST |
| 103 | ++ |
| 104 | + /* Test an external entity parser set to use latin-1 detects UTF-16 |
| 105 | + * BOMs correctly. |
| 106 | + */ |
| 107 | +@@ -6284,6 +6324,8 @@ make_basic_test_case(Suite *s) { |
| 108 | + tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate); |
| 109 | + tcase_add_test(tc_basic, test_unknown_encoding_invalid_high); |
| 110 | + tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value); |
| 111 | ++ tcase_add_test(tc_basic, test_unknown_encoding_user_data_primary); |
| 112 | ++ tcase_add_test(tc_basic, test_unknown_encoding_user_data_secondary); |
| 113 | + tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16le_bom); |
| 114 | + tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16be_bom); |
| 115 | + tcase_add_test__if_xml_ge(tc_basic, test_ext_entity_latin1_utf16le_bom2); |
| 116 | +diff --git a/tests/handlers.c b/tests/handlers.c |
| 117 | +index bdb5b0e..5078014 100644 |
| 118 | +--- a/tests/handlers.c |
| 119 | ++++ b/tests/handlers.c |
| 120 | +@@ -45,6 +45,7 @@ |
| 121 | + # undef NDEBUG /* because test suite relies on assert(...) at the moment */ |
| 122 | + #endif |
| 123 | + |
| 124 | ++#include <stdint.h> |
| 125 | + #include <stdio.h> |
| 126 | + #include <string.h> |
| 127 | + #include <assert.h> |
| 128 | +@@ -407,6 +408,15 @@ long_encoding_handler(void *userData, const XML_Char *encoding, |
| 129 | + return XML_STATUS_OK; |
| 130 | + } |
| 131 | + |
| 132 | ++int XMLCALL |
| 133 | ++user_data_checking_unknown_encoding_handler(void *userData, |
| 134 | ++ const XML_Char *encoding, |
| 135 | ++ XML_Encoding *info) { |
| 136 | ++ const intptr_t number = (intptr_t)userData; |
| 137 | ++ assert_true(number == 0xC0FFEE); |
| 138 | ++ return long_encoding_handler(userData, encoding, info); |
| 139 | ++} |
| 140 | ++ |
| 141 | + /* External Entity Handlers */ |
| 142 | + |
| 143 | + int XMLCALL |
| 144 | +diff --git a/tests/handlers.h b/tests/handlers.h |
| 145 | +index 4d6a08d..ac4ca94 100644 |
| 146 | +--- a/tests/handlers.h |
| 147 | ++++ b/tests/handlers.h |
| 148 | +@@ -159,6 +159,9 @@ extern int XMLCALL long_encoding_handler(void *userData, |
| 149 | + const XML_Char *encoding, |
| 150 | + XML_Encoding *info); |
| 151 | + |
| 152 | ++extern int XMLCALL user_data_checking_unknown_encoding_handler( |
| 153 | ++ void *userData, const XML_Char *encoding, XML_Encoding *info); |
| 154 | ++ |
| 155 | + /* External Entity Handlers */ |
| 156 | + |
| 157 | + typedef struct ExtOption { |
| 158 | +-- |
| 159 | +2.45.4 |
| 160 | + |
| 161 | + |
| 162 | +From c18cd2b13f2428c8a740b285fb2d2bc710f4f1bb Mon Sep 17 00:00:00 2001 |
| 163 | +From: Sebastian Pipping <sebastian@pipping.org> |
| 164 | +Date: Sun, 18 Jan 2026 18:19:25 +0100 |
| 165 | +Subject: [PATCH 3/3] Changes: Document CVE-2026-24515 |
| 166 | + |
| 167 | +-- |
| 168 | +2.45.4 |
| 169 | + |
0 commit comments