untrusted comment: verify with openbsd-77-base.pub RWSbCCUoGpcxVaVGuzTrWKhO4QM8M0T0XYqOKay4z5Mcfm8wRNLm7+79uA8vpZI+cKRrpiaLa/5zr0gSLND0s+p0R0NmG73I0wA= OpenBSD 7.7 errata 020, February 9, 2026: In libexpat fix denial of service due to NULL dereference and integer overflow. CVE-2026-24515 CVE-2026-25210 Apply by doing: signify -Vep /etc/signify/openbsd-77-base.pub -x 020_expat.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install libexpat: cd /usr/src/lib/libexpat make obj make make install Index: lib/libexpat/Changes =================================================================== RCS file: /cvs/src/lib/libexpat/Changes,v diff -u -p -r1.30.4.1 Changes --- lib/libexpat/Changes 28 Sep 2025 22:22:54 -0000 1.30.4.1 +++ lib/libexpat/Changes 2 Feb 2026 23:05:00 -0000 @@ -38,6 +38,23 @@ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Security fixes: + #1131 CVE-2026-24515 -- Function XML_ExternalEntityParserCreate + failed to copy the encoding handler data passed to + XML_SetUnknownEncodingHandler from the parent to the new + subparser. This can cause a NULL dereference (CWE-476) from + external entities that declare use of an unknown encoding. + The expected impact is denial of service. It takes use of + both functions XML_ExternalEntityParserCreate and + XML_SetUnknownEncodingHandler for an application to be + vulnerable. + #1075 CVE-2026-25210 -- Add missing check for integer overflow + related to buffer size determination in function doContent + + Bug fixes: + #1073 lib: Fix missing undoing of group size expansion in doProlog + failure cases + + Security fixes: #1046 #1048 Fix alignment of internal allocations for some non-amd64 architectures (e.g. sparc32); fixes up on the fix to CVE-2025-59375 from #1034 (of Expat 2.7.2 and related Index: lib/libexpat/lib/xmlparse.c =================================================================== RCS file: /cvs/src/lib/libexpat/lib/xmlparse.c,v diff -u -p -r1.42.4.1 xmlparse.c --- lib/libexpat/lib/xmlparse.c 28 Sep 2025 22:22:54 -0000 1.42.4.1 +++ lib/libexpat/lib/xmlparse.c 2 Feb 2026 23:05:02 -0000 @@ -13,7 +13,7 @@ Copyright (c) 2002-2016 Karl Waclawek Copyright (c) 2005-2009 Steven Solie Copyright (c) 2016 Eric Rahm - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2016 Gaurav Copyright (c) 2016 Thomas Beutlich Copyright (c) 2016 Gustavo Grieco @@ -1737,6 +1737,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; @@ -1782,6 +1783,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; @@ -1842,6 +1844,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; @@ -3443,7 +3446,6 @@ doContent(XML_Parser parser, int startTa const char *fromPtr = tag->rawName; toPtr = (XML_Char *)tag->buf; for (;;) { - int bufSize; int convLen; const enum XML_Convert_Result convert_res = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr, @@ -3454,7 +3456,9 @@ doContent(XML_Parser parser, int startTa tag->name.strLen = convLen; break; } - bufSize = (int)(tag->bufEnd - tag->buf) << 1; + if (SIZE_MAX / 2 < (size_t)(tag->bufEnd - tag->buf)) + return XML_ERROR_NO_MEMORY; + const size_t bufSize = (size_t)(tag->bufEnd - tag->buf) * 2; { char *temp = REALLOC(parser, tag->buf, bufSize); if (temp == NULL) @@ -5872,14 +5876,17 @@ doProlog(XML_Parser parser, const ENCODI * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) { + parser->m_groupSize /= 2; return XML_ERROR_NO_MEMORY; } #endif int *const new_scaff_index = REALLOC( parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int)); - if (new_scaff_index == NULL) + if (new_scaff_index == NULL) { + parser->m_groupSize /= 2; return XML_ERROR_NO_MEMORY; + } dtd->scaffIndex = new_scaff_index; } } else { Index: lib/libexpat/tests/basic_tests.c =================================================================== RCS file: /cvs/src/lib/libexpat/tests/basic_tests.c,v diff -u -p -r1.6 basic_tests.c --- lib/libexpat/tests/basic_tests.c 14 Mar 2025 20:20:30 -0000 1.6 +++ lib/libexpat/tests/basic_tests.c 2 Feb 2026 23:05:03 -0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2025 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -4566,6 +4566,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 = "\n" + "\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 = "\n" + "]>\n" + "&ext;\n"; + const char *const text_external = "\n" + "data"; + 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: lib/libexpat/tests/handlers.c =================================================================== RCS file: /cvs/src/lib/libexpat/tests/handlers.c,v diff -u -p -r1.3 handlers.c --- lib/libexpat/tests/handlers.c 14 Mar 2025 20:20:30 -0000 1.3 +++ lib/libexpat/tests/handlers.c 2 Feb 2026 23:05:03 -0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2024 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -45,6 +45,7 @@ # undef NDEBUG /* because test suite relies on assert(...) at the moment */ #endif +#include #include #include #include @@ -405,6 +406,15 @@ long_encoding_handler(void *userData, co info->convert = NULL; info->release = NULL; 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 */ Index: lib/libexpat/tests/handlers.h =================================================================== RCS file: /cvs/src/lib/libexpat/tests/handlers.h,v diff -u -p -r1.3 handlers.h --- lib/libexpat/tests/handlers.h 14 Mar 2025 20:20:30 -0000 1.3 +++ lib/libexpat/tests/handlers.h 2 Feb 2026 23:05:04 -0000 @@ -10,7 +10,7 @@ Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek - Copyright (c) 2016-2024 Sebastian Pipping + Copyright (c) 2016-2026 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha @@ -158,6 +158,9 @@ extern int XMLCALL MiscEncodingHandler(v extern int XMLCALL long_encoding_handler(void *userData, 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 */