new file mode 100644
@@ -0,0 +1,80 @@
+From 9d1c131840a501e6664c5770046153235467f574 Mon Sep 17 00:00:00 2001
+From: Matthew Fernandez <matthew.fernandez@gmail.com>
+Date: Thu, 4 Jun 2026 17:01:02 -0700
+Subject: [PATCH 13/17] lib: Remove reuse of `m_groupSize` to count
+ `m_scaffIndex` allocation
+
+The sizes of the two arrays `m_groupConnector` and `scaffIndex` need to
+vary independently. This change is a step towards allowing this.
+
+Anthropic: ANT-2026-00037
+Anthropic: ANT-2026-03621
+Anthropic: ANT-2026-03867
+Co-authored-by: Alessandro Gario <alessandro.gario@trailofbits.com>
+
+CVE: CVE-2026-56132
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/3a4eaf47af8fd7abda38ea2c08308c91152061f3]
+
+Backport Changes:
+- Adapt scaffIndex sizing to Scarthgap 2.6.4, where m_groupSize is
+ not temporarily doubled before reallocation.
+ Keep the branch's equivalent size_t overflow check.
+
+(cherry picked from commit 3a4eaf47af8fd7abda38ea2c08308c91152061f3)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ expat/lib/xmlparse.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
+index 8439dc0e..e9ad78df 100644
+--- a/expat/lib/xmlparse.c
++++ b/expat/lib/xmlparse.c
+@@ -423,6 +423,7 @@ typedef struct {
+ unsigned scaffCount;
+ int scaffLevel;
+ int *scaffIndex;
++ size_t scaffIndexSize;
+ } DTD;
+
+ enum EntityType {
+@@ -5975,6 +5976,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
+ if (new_scaff_index == NULL)
+ return XML_ERROR_NO_MEMORY;
+ dtd->scaffIndex = new_scaff_index;
++ dtd->scaffIndexSize = parser->m_groupSize;
+ }
+ } else {
+ parser->m_groupConnector = MALLOC(parser, parser->m_groupSize = 32);
+@@ -7575,6 +7577,7 @@ dtdCreate(XML_Parser parser) {
+
+ p->in_eldecl = XML_FALSE;
+ p->scaffIndex = NULL;
++ p->scaffIndexSize = 0;
+ p->scaffold = NULL;
+ p->scaffLevel = 0;
+ p->scaffSize = 0;
+@@ -7615,6 +7618,7 @@ dtdReset(DTD *p, XML_Parser parser) {
+
+ FREE(parser, p->scaffIndex);
+ p->scaffIndex = NULL;
++ p->scaffIndexSize = 0;
+ FREE(parser, p->scaffold);
+ p->scaffold = NULL;
+
+@@ -7790,6 +7794,7 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
+ newDtd->scaffSize = oldDtd->scaffSize;
+ newDtd->scaffLevel = oldDtd->scaffLevel;
+ newDtd->scaffIndex = oldDtd->scaffIndex;
++ newDtd->scaffIndexSize = oldDtd->scaffIndexSize;
+
+ return 1;
+ } /* End dtdCopy */
+@@ -8310,6 +8315,7 @@ nextScaffoldPart(XML_Parser parser) {
+ dtd->scaffIndex = MALLOC(parser, parser->m_groupSize * sizeof(int));
+ if (! dtd->scaffIndex)
+ return -1;
++ dtd->scaffIndexSize = parser->m_groupSize;
+ dtd->scaffIndex[0] = 0;
+ }
+
new file mode 100644
@@ -0,0 +1,60 @@
+From a4c1b874dffcc80ee63ca3b4d6a1537c56da8dc1 Mon Sep 17 00:00:00 2001
+From: Matthew Fernandez <matthew.fernandez@gmail.com>
+Date: Thu, 4 Jun 2026 17:01:02 -0700
+Subject: [PATCH 14/17] lib: doProlog: Fix out-of-bound scaffolding index store
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The scaffold backing array is reallocated using the caller parser’s
+per-parser `m_groupSize`, but the DTD struct (which carries
+`scaffIndex`) is shared between a parent parser and any external
+parameter-entity sub-parser created via
+`XML_ExternalEntityParserCreate(parent, NULL, …)`. A sub-parser whose
+group nesting is shallower than the parent’s can `REALLOC` the shared
+`scaffIndex` down to its own size; when the parent resumes and parses a
+deeper element content model, its bounds check passes (its private
+`m_groupSize` is still large enough), the doubling-grow path is skipped,
+and the next write lands past the shrunken buffer.
+
+Anthropic: ANT-2026-00037
+Anthropic: ANT-2026-03621
+Anthropic: ANT-2026-03867
+Co-authored-by: Alessandro Gario <alessandro.gario@trailofbits.com>
+Reported-by: Trail of Bits, in collaboration with Anthropic
+
+CVE: CVE-2026-56132
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/58400483d7c97be316d7a77739c0a6af5d55932e]
+
+(cherry picked from commit 58400483d7c97be316d7a77739c0a6af5d55932e)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ expat/lib/xmlparse.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
+index e9ad78df..c46c17bc 100644
+--- a/expat/lib/xmlparse.c
++++ b/expat/lib/xmlparse.c
+@@ -5992,6 +5992,21 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
+ if (myindex < 0)
+ return XML_ERROR_NO_MEMORY;
+ assert(dtd->scaffIndex != NULL);
++ if ((size_t)dtd->scaffLevel >= dtd->scaffIndexSize) {
++ /* Detect and prevent integer overflow */
++ if (dtd->scaffIndexSize > SIZE_MAX / 2 / sizeof(int)) {
++ return XML_ERROR_NO_MEMORY;
++ }
++ assert(dtd->scaffIndexSize > 0);
++ const size_t new_size = dtd->scaffIndexSize * 2;
++ int *const new_scaff_index
++ = REALLOC(parser, dtd->scaffIndex, new_size * sizeof(int));
++ if (new_scaff_index == NULL) {
++ return XML_ERROR_NO_MEMORY;
++ }
++ dtd->scaffIndex = new_scaff_index;
++ dtd->scaffIndexSize = new_size;
++ }
+ dtd->scaffIndex[dtd->scaffLevel] = myindex;
+ dtd->scaffLevel++;
+ dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
new file mode 100644
@@ -0,0 +1,74 @@
+From 5d4d0dab46e077b327f70a7c02a307287e8d1fe5 Mon Sep 17 00:00:00 2001
+From: Matthew Fernandez <matthew.fernandez@gmail.com>
+Date: Thu, 4 Jun 2026 17:01:02 -0700
+Subject: [PATCH 15/17] tests: Add a test case for scaffolding array limits in
+ shared DTDs
+
+This test case provokes the bug fixed in the previous commit.
+
+Anthropic: ANT-2026-00037
+Anthropic: ANT-2026-03621
+Anthropic: ANT-2026-03867
+Co-authored-by: Alessandro Gario <alessandro.gario@trailofbits.com>
+Reported-by: Trail of Bits, in collaboration with Anthropic
+
+CVE: CVE-2026-56132
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/353919b3b9f2174073a557ac7d517a5f3cd0cbbf]
+
+(cherry picked from commit 353919b3b9f2174073a557ac7d517a5f3cd0cbbf)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ expat/tests/basic_tests.c | 33 +++++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+diff --git a/expat/tests/basic_tests.c b/expat/tests/basic_tests.c
+index 023d9ce4..d52dcf1c 100644
+--- a/expat/tests/basic_tests.c
++++ b/expat/tests/basic_tests.c
+@@ -4044,6 +4044,37 @@ START_TEST(test_skipped_external_entity) {
+ }
+ END_TEST
+
++START_TEST(test_scaff_index_shared_across_external_entity_parser) {
++ const char text[]
++ = "<!DOCTYPE doc [\n"
++ "<!ELEMENT a "
++ "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((b))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>\n"
++ "<!ENTITY % e SYSTEM 'ext'>\n"
++ "%e;\n"
++ "<!ELEMENT c "
++ "(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((d)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>\n"
++ "]>\n"
++ "<doc/>";
++ ExtOption options[]
++ = {{XCS("ext"),
++ "<!ELEMENT x "
++ "((((((((((((((((((((((((((((((((y))))))))))))))))))))))))))))))))>"},
++ {NULL, NULL}};
++
++ XML_Parser parser = XML_ParserCreate(NULL);
++ XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
++ XML_SetUserData(parser, options);
++ XML_SetExternalEntityRefHandler(parser, external_entity_optioner);
++ XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
++
++ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
++ == XML_STATUS_ERROR)
++ xml_failure(parser);
++
++ XML_ParserFree(parser);
++}
++END_TEST
++
+ /* Test a different form of unknown external entity */
+ START_TEST(test_skipped_null_loaded_ext_entity) {
+ const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
+@@ -6399,6 +6430,8 @@ make_basic_test_case(Suite *s) {
+ tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
+ tcase_add_test(tc_basic, test_standalone_internal_entity);
+ tcase_add_test(tc_basic, test_skipped_external_entity);
++ tcase_add_test__ifdef_xml_dtd(
++ tc_basic, test_scaff_index_shared_across_external_entity_parser);
+ tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
+ tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
+ tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
new file mode 100644
@@ -0,0 +1,60 @@
+From a7d7ed5d6dbcc7231529357d64eb19ede3114868 Mon Sep 17 00:00:00 2001
+From: Matthew Fernandez <matthew.fernandez@gmail.com>
+Date: Thu, 4 Jun 2026 17:01:02 -0700
+Subject: [PATCH 16/17] lib: Remove unnecessary `scaffIndex` expansion
+
+Following the previous changes, all locations that append entries to
+`scaffIndex` handle expanding the array if it is not already large
+enough. So this extra expansion code is no longer necessary. In some
+cases such as processing siblings with alternating scaffolding counts,
+this logic would actually _shrink_ the array only to then later
+re-expand it.
+
+Anthropic: ANT-2026-00037
+Anthropic: ANT-2026-03621
+Anthropic: ANT-2026-03867
+Co-authored-by: Alessandro Gario <alessandro.gario@trailofbits.com>
+
+CVE: CVE-2026-56132
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/bca93b4ba9e15fd84425568d772b69baebf790e4]
+
+Backport Changes:
+- Remove the Scarthgap 2.6.4 scaffIndex resize block because later
+ append paths already expand the array when required.
+
+(cherry picked from commit bca93b4ba9e15fd84425568d772b69baebf790e4)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ expat/lib/xmlparse.c | 19 -------------------
+ 1 file changed, 19 deletions(-)
+
+diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
+index c46c17bc..3afe2884 100644
+--- a/expat/lib/xmlparse.c
++++ b/expat/lib/xmlparse.c
+@@ -5959,25 +5959,6 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
+ }
+ parser->m_groupConnector = new_connector;
+ }
+-
+- if (dtd->scaffIndex) {
+- /* Detect and prevent integer overflow.
+- * The preprocessor guard addresses the "always false" warning
+- * from -Wtype-limits on platforms where
+- * 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)) {
+- 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)
+- return XML_ERROR_NO_MEMORY;
+- dtd->scaffIndex = new_scaff_index;
+- dtd->scaffIndexSize = parser->m_groupSize;
+- }
+ } else {
+ parser->m_groupConnector = MALLOC(parser, parser->m_groupSize = 32);
+ if (! parser->m_groupConnector) {
new file mode 100644
@@ -0,0 +1,56 @@
+From 778ba31c47f9930fe339194f4d97081e43893362 Mon Sep 17 00:00:00 2001
+From: Matthew Fernandez <matthew.fernandez@gmail.com>
+Date: Thu, 4 Jun 2026 17:01:02 -0700
+Subject: [PATCH 17/17] lib: Remove indented scoping of `new_connector` local
+
+Following the previous change, the lifetime of `new_connector` as
+constrained by this introduced scope was identical to the parent scope.
+
+CVE: CVE-2026-56132
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/08baa7ef9d168b99094249998fd78f8d190526e5]
+
+Backport Changes:
+- Retain the Scarthgap 2.6.4 unsigned integer overflow guard while
+ removing only the redundant new_connector scope.
+
+(cherry picked from commit 08baa7ef9d168b99094249998fd78f8d190526e5)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ expat/lib/xmlparse.c | 22 ++++++++++------------
+ 1 file changed, 10 insertions(+), 12 deletions(-)
+
+diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
+index 3afe2884..df8331d5 100644
+--- a/expat/lib/xmlparse.c
++++ b/expat/lib/xmlparse.c
+@@ -5945,20 +5945,18 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
+ case XML_ROLE_GROUP_OPEN:
+ if (parser->m_prologState.level >= parser->m_groupSize) {
+ if (parser->m_groupSize) {
+- {
+- /* Detect and prevent integer overflow */
+- if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
+- return XML_ERROR_NO_MEMORY;
+- }
++ /* Detect and prevent integer overflow */
++ if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
++ return XML_ERROR_NO_MEMORY;
++ }
+
+- char *const new_connector = REALLOC(
+- parser, parser->m_groupConnector, parser->m_groupSize *= 2);
+- if (new_connector == NULL) {
+- parser->m_groupSize /= 2;
+- return XML_ERROR_NO_MEMORY;
+- }
+- parser->m_groupConnector = new_connector;
++ char *const new_connector = REALLOC(parser, parser->m_groupConnector,
++ parser->m_groupSize *= 2);
++ if (new_connector == NULL) {
++ parser->m_groupSize /= 2;
++ return XML_ERROR_NO_MEMORY;
+ }
++ parser->m_groupConnector = new_connector;
+ } else {
+ parser->m_groupConnector = MALLOC(parser, parser->m_groupSize = 32);
+ if (! parser->m_groupConnector) {
@@ -63,6 +63,11 @@ SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \
file://CVE-2026-56409.patch;striplevel=2 \
file://CVE-2026-56411.patch;striplevel=2 \
file://CVE-2026-56407.patch;striplevel=2 \
+ file://CVE-2026-56132_p1.patch;striplevel=2 \
+ file://CVE-2026-56132_p2.patch;striplevel=2 \
+ file://CVE-2026-56132_p3.patch;striplevel=2 \
+ file://CVE-2026-56132_p4.patch;striplevel=2 \
+ file://CVE-2026-56132_p5.patch;striplevel=2 \
"
GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"