From: Peter Marko <[email protected]> Pick patches per [1].
[1] https://security-tracker.debian.org/tracker/CVE-2026-76957 Signed-off-by: Peter Marko <[email protected]> --- .../expat/expat/CVE-2026-76957-01.patch | 121 ++++++++++++++++++ .../expat/expat/CVE-2026-76957-02.patch | 85 ++++++++++++ meta/recipes-core/expat/expat_2.8.3.bb | 2 + 3 files changed, 208 insertions(+) create mode 100644 meta/recipes-core/expat/expat/CVE-2026-76957-01.patch create mode 100644 meta/recipes-core/expat/expat/CVE-2026-76957-02.patch diff --git a/meta/recipes-core/expat/expat/CVE-2026-76957-01.patch b/meta/recipes-core/expat/expat/CVE-2026-76957-01.patch new file mode 100644 index 0000000000..fb7a8e0b02 --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2026-76957-01.patch @@ -0,0 +1,121 @@ +From 127b7d4beb8fe7e5ce5cb021c2e56379c95863d0 Mon Sep 17 00:00:00 2001 +From: Darren Carreras <[email protected]> +Date: Mon, 17 Aug 2026 21:16:00 -0400 +Subject: [PATCH] Protect custom encoding callbacks from parser reentry + +Co-authored-by: Sebastian Pipping <[email protected]> + +CVE: CVE-2026-76957 +Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/127b7d4beb8fe7e5ce5cb021c2e56379c95863d0] +Signed-off-by: Peter Marko <[email protected]> +--- + lib/xmlparse.c | 49 ++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 40 insertions(+), 9 deletions(-) + +diff --git a/lib/xmlparse.c b/lib/xmlparse.c +index e5242480..4f9dcbb6 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -771,6 +771,8 @@ struct XML_ParserStruct { + void *m_unknownEncodingMem; + void *m_unknownEncodingData; + void *m_unknownEncodingHandlerData; ++ // Application callback invoked by callUnknownEncodingConvert. ++ int(XMLCALL *m_unknownEncodingConvert)(void *, const char *); + void(XMLCALL *m_unknownEncodingRelease)(void *); + PROLOG_STATE m_prologState; + Processor *m_processor; +@@ -1193,6 +1195,25 @@ isCalledFromInsideHandler(XML_Parser parser) { + return parser->m_handlerCallDepth > 0; + } + ++static void ++callUnknownEncodingRelease(XML_Parser parser) { ++ beforeHandler(parser); ++ parser->m_unknownEncodingRelease(parser->m_unknownEncodingData); ++ afterHandler(parser); ++ parser->m_unknownEncodingRelease = NULL; ++ parser->m_unknownEncodingData = NULL; ++} ++ ++static int XMLCALL ++callUnknownEncodingConvert(void *data, const char *p) { ++ XML_Parser parser = data; ++ beforeHandler(parser); ++ const int result ++ = parser->m_unknownEncodingConvert(parser->m_unknownEncodingData, p); ++ afterHandler(parser); ++ return result; ++} ++ + static enum XML_Error + callProcessor(XML_Parser parser, const char *start, const char *end, + const char **endPtr) { +@@ -1540,6 +1561,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) { + parser->m_inheritedBindings = NULL; + parser->m_nSpecifiedAtts = 0; + parser->m_unknownEncodingMem = NULL; ++ parser->m_unknownEncodingConvert = NULL; + parser->m_unknownEncodingRelease = NULL; + parser->m_unknownEncodingData = NULL; + parser->m_parsingStatus.parsing = XML_INITIALIZED; +@@ -1620,7 +1642,7 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { + moveToFreeBindingList(parser, parser->m_inheritedBindings); + FREE(parser, parser->m_unknownEncodingMem); + if (parser->m_unknownEncodingRelease) +- parser->m_unknownEncodingRelease(parser->m_unknownEncodingData); ++ callUnknownEncodingRelease(parser); + poolClear(&parser->m_tempPool); + poolClear(&parser->m_temp2Pool); + FREE(parser, (void *)parser->m_protocolEncodingName); +@@ -1931,7 +1953,7 @@ XML_ParserFree(XML_Parser parser) { + FREE(parser, parser->m_nsAtts); + FREE(parser, parser->m_unknownEncodingMem); + if (parser->m_unknownEncodingRelease) +- parser->m_unknownEncodingRelease(parser->m_unknownEncodingData); ++ callUnknownEncodingRelease(parser); + FREE(parser, parser); + } + +@@ -4965,25 +4987,34 @@ handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) { + const int status = parser->m_unknownEncodingHandler( + parser->m_unknownEncodingHandlerData, encodingName, &info); + afterHandler(parser); ++ ++ parser->m_unknownEncodingRelease = info.release; ++ parser->m_unknownEncodingData = info.data; ++ + if (status) { + ENCODING *enc; + parser->m_unknownEncodingMem = MALLOC(parser, XmlSizeOfUnknownEncoding()); + if (! parser->m_unknownEncodingMem) { +- if (info.release) +- info.release(info.data); ++ if (parser->m_unknownEncodingRelease) ++ callUnknownEncodingRelease(parser); ++ else ++ parser->m_unknownEncodingData = NULL; + return XML_ERROR_NO_MEMORY; + } ++ parser->m_unknownEncodingConvert = info.convert; + enc = (parser->m_ns ? XmlInitUnknownEncodingNS : XmlInitUnknownEncoding)( +- parser->m_unknownEncodingMem, info.map, info.convert, info.data); ++ parser->m_unknownEncodingMem, info.map, ++ info.convert ? callUnknownEncodingConvert : NULL, parser); + if (enc) { +- parser->m_unknownEncodingData = info.data; +- parser->m_unknownEncodingRelease = info.release; + parser->m_encoding = enc; + return XML_ERROR_NONE; + } ++ parser->m_unknownEncodingConvert = NULL; + } +- if (info.release != NULL) +- info.release(info.data); ++ if (parser->m_unknownEncodingRelease != NULL) ++ callUnknownEncodingRelease(parser); ++ else ++ parser->m_unknownEncodingData = NULL; + } + return XML_ERROR_UNKNOWN_ENCODING; + } diff --git a/meta/recipes-core/expat/expat/CVE-2026-76957-02.patch b/meta/recipes-core/expat/expat/CVE-2026-76957-02.patch new file mode 100644 index 0000000000..827499958a --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2026-76957-02.patch @@ -0,0 +1,85 @@ +From acbd2e1179c04fe9a8c3f3837701904d05de71fc Mon Sep 17 00:00:00 2001 +From: Darren Carreras <[email protected]> +Date: Mon, 17 Aug 2026 21:19:12 -0400 +Subject: [PATCH] Test custom encoding callback reentry protection + +CVE: CVE-2026-76957 +Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/acbd2e1179c04fe9a8c3f3837701904d05de71fc] +Signed-off-by: Peter Marko <[email protected]> +--- + tests/misc_tests.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 55 insertions(+) + +diff --git a/tests/misc_tests.c b/tests/misc_tests.c +index 82b4b54b..04538c25 100644 +--- a/tests/misc_tests.c ++++ b/tests/misc_tests.c +@@ -839,6 +839,60 @@ START_TEST(test_misc_resume_parser_forbidden_from_handler) { + } + END_TEST + ++typedef struct { ++ XML_Parser parser; ++ int converterCallCount; ++ int releaseCallCount; ++} EncodingCallbackData; ++ ++static int XMLCALL ++reentrant_encoding_converter(void *userData, const char *s) { ++ EncodingCallbackData *const data = userData; ++ UNUSED_P(s); ++ data->converterCallCount++; ++ forbidden_calls_character_handler(data->parser, NULL, 0); ++ return 'A'; ++} ++ ++static void XMLCALL ++reentrant_encoding_release(void *userData) { ++ EncodingCallbackData *const data = userData; ++ data->releaseCallCount++; ++ forbidden_calls_character_handler(data->parser, NULL, 0); ++} ++ ++static int XMLCALL ++reentrant_encoding_handler(void *userData, const XML_Char *name, ++ XML_Encoding *info) { ++ EncodingCallbackData *const data = userData; ++ UNUSED_P(name); ++ ++ for (int i = 0; i < 256; i++) ++ info->map[i] = i; ++ info->map[0x80] = -2; // Route byte 0x80 through the custom converter. ++ info->data = data; ++ info->convert = reentrant_encoding_converter; ++ info->release = reentrant_encoding_release; ++ return XML_STATUS_OK; ++} ++ ++START_TEST(test_misc_unknown_encoding_callbacks_protected) { ++ const char *const doc ++ = "<?xml version='1.0' encoding='reentrant-conv'?><doc>\x80\x80</doc>"; ++ XML_Parser parser = XML_ParserCreate(NULL); ++ EncodingCallbackData data = {parser, 0, 0}; ++ XML_SetUnknownEncodingHandler(parser, reentrant_encoding_handler, &data); ++ ++ assert_true(XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_TRUE) ++ == XML_STATUS_OK); ++ assert_true(data.converterCallCount > 0); ++ assert_true(data.releaseCallCount == 0); // Released by XML_ParserFree below. ++ ++ XML_ParserFree(parser); ++ assert_true(data.releaseCallCount == 1); ++} ++END_TEST ++ + // General attack payload idea by Jason Kratzer of Mozilla + START_TEST(test_misc_low_surrogate_mozilla_bug_2053153) { + const char doc_before[] = "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0" +@@ -936,6 +990,7 @@ make_miscellaneous_test_case(Suite *s) { + tcase_add_test(tc_misc, test_misc_no_infinite_loop_issue_1161); + tcase_add_test(tc_misc, test_misc_calls_forbidden_from_handlers); + tcase_add_test(tc_misc, test_misc_resume_parser_forbidden_from_handler); ++ tcase_add_test(tc_misc, test_misc_unknown_encoding_callbacks_protected); + tcase_add_test(tc_misc, test_misc_input_2gb); + tcase_add_test(tc_misc, test_misc_low_surrogate_mozilla_bug_2053153); + } diff --git a/meta/recipes-core/expat/expat_2.8.3.bb b/meta/recipes-core/expat/expat_2.8.3.bb index c3c9f73845..c9a1c9b18e 100644 --- a/meta/recipes-core/expat/expat_2.8.3.bb +++ b/meta/recipes-core/expat/expat_2.8.3.bb @@ -14,6 +14,8 @@ SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \ file://CVE-2026-66046-02.patch \ file://CVE-2026-76641.patch \ file://CVE-2026-76956.patch \ + file://CVE-2026-76957-01.patch \ + file://CVE-2026-76957-02.patch \ " GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#247322): https://lists.openembedded.org/g/openembedded-core/message/247322 Mute This Topic: https://lists.openembedded.org/mt/121616555/21656 Group Owner: [email protected] Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
