new file mode 100644
@@ -0,0 +1,30 @@
+From bfc28346fa3efeb8ca56c17437d24a7344e5feab Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Mon, 26 Oct 2026 17:39:32 +0100
+Subject: [PATCH] lib: Fix initial non-final empty subparser call with a
+ handler
+
+CVE: CVE-2026-117610
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/bfc28346fa3efeb8ca56c17437d24a7344e5feab]
+
+Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
+---
+ lib/xmlparse.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index a0946be..b17f5e0 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -3233,6 +3233,11 @@ externalEntityInitProcessor2(XML_Parser parser, const char *start,
+ }
+ parser->m_eventPtr = start;
+ return XML_ERROR_PARTIAL_CHAR;
++ case XML_TOK_NONE:
++ if (! parser->m_parsingStatus.finalBuffer) {
++ *endPtr = start;
++ }
++ return XML_ERROR_NONE;
+ }
+ parser->m_processor = externalEntityInitProcessor3;
+ return externalEntityInitProcessor3(parser, start, end, endPtr);
new file mode 100644
@@ -0,0 +1,92 @@
+From cedb704d2cad9d6ef77f8f172104d3e751eccfd2 Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Mon, 26 Oct 2026 17:17:57 +0100
+Subject: [PATCH] tests: Add a test for a initial non-final empty subparser
+ parse
+
+.. with a handler call
+
+CVE: CVE-2026-117610
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/cedb704d2cad9d6ef77f8f172104d3e751eccfd2]
+
+Backport Changes:
+- Compare handler data with the existing XCS macro and xcstrcmp test
+ helper in Expat 2.8.3. This replaces xcsdup_str allocations,
+ allocation assertions and frees, avoiding the newer xcs helpers.
+
+Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
+---
+ tests/misc_tests.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 55 insertions(+)
+
+diff --git a/tests/misc_tests.c b/tests/misc_tests.c
+index 04538c2..6c82715 100644
+--- a/tests/misc_tests.c
++++ b/tests/misc_tests.c
+@@ -957,6 +957,60 @@ START_TEST(test_misc_input_2gb) {
+ }
+ END_TEST
+
++static void
++comparingPiHandler(void *userData, const XML_Char *target,
++ const XML_Char *data) {
++ UNUSED_P(userData);
++
++ assert_true(xcstrcmp(target, XCS("target")) == 0);
++ assert_true(xcstrcmp(data, XCS("data")) == 0);
++}
++
++static int XMLCALL
++piParsingExternalEntityHandler(XML_Parser parent, const XML_Char *context,
++ const XML_Char *base, const XML_Char *systemId,
++ const XML_Char *publicId) {
++ UNUSED_P(base);
++ UNUSED_P(systemId);
++ UNUSED_P(publicId);
++
++ const char *const doc = "<?target data?>";
++
++ XML_Parser subParser = XML_ExternalEntityParserCreate(parent, context, NULL);
++ assert_true(subParser != NULL);
++
++ // NOTE: Related test "test_empty_ext_param_entity_in_value" could be of
++ // interest
++ assert_true(_XML_Parse_SINGLE_BYTES(subParser, "", 0, /*isFinal=*/XML_FALSE)
++ == XML_STATUS_OK);
++ assert_true(_XML_Parse_SINGLE_BYTES(subParser, doc, (int)strlen(doc),
++ /*isFinal=*/XML_TRUE)
++ == XML_STATUS_OK);
++
++ XML_ParserFree(subParser);
++
++ return XML_STATUS_OK;
++}
++
++START_TEST(test_misc_empty_nonfinal_subparser_parse) {
++ const char *const doc = "<!DOCTYPE root [\n"
++ " <!ENTITY ext SYSTEM 'external.dtd'>\n"
++ "]>\n"
++ "<root>&ext;</root>\n";
++
++ XML_Parser parser = XML_ParserCreate(NULL);
++ assert_true(parser != NULL);
++
++ XML_SetProcessingInstructionHandler(parser, comparingPiHandler);
++ XML_SetExternalEntityRefHandler(parser, piParsingExternalEntityHandler);
++
++ assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
++ /*isFinal=*/XML_TRUE));
++
++ XML_ParserFree(parser);
++}
++END_TEST
++
+ void
+ make_miscellaneous_test_case(Suite *s) {
+ TCase *tc_misc = tcase_create("miscellaneous tests");
+@@ -993,4 +1047,5 @@ make_miscellaneous_test_case(Suite *s) {
+ 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);
++ tcase_add_test(tc_misc, test_misc_empty_nonfinal_subparser_parse);
+ }
@@ -25,6 +25,8 @@ SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \
file://CVE-2026-113351_p3.patch \
file://CVE-2026-113351_p4.patch \
file://CVE-2026-113351_p5.patch \
+ file://CVE-2026-117610_p1.patch \
+ file://CVE-2026-117610_p2.patch \
"
GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"