mirror of
https://git.yoctoproject.org/poky
synced 2026-09-01 02:30:13 +00:00
expat: fix CVE-2026-56132
These patches apply the upstream fix shown in [2], its prerequisite [1], the regression test in [3], and the follow-up cleanups in [4] and [5], as referenced by [6]. [1] https://github.com/libexpat/libexpat/commit/3a4eaf47af8fd7abda38ea2c08308c91152061f3 [2] https://github.com/libexpat/libexpat/commit/58400483d7c97be316d7a77739c0a6af5d55932e [3] https://github.com/libexpat/libexpat/commit/353919b3b9f2174073a557ac7d517a5f3cd0cbbf [4] https://github.com/libexpat/libexpat/commit/bca93b4ba9e15fd84425568d772b69baebf790e4 [5] https://github.com/libexpat/libexpat/commit/08baa7ef9d168b99094249998fd78f8d190526e5 [6] https://nvd.nist.gov/vuln/detail/CVE-2026-56132 (From OE-Core rev: 0cba8f866ffe5b96dd7f2a8fe7b4c52264d382c5) Signed-off-by: Deepak Rathore <deeratho@cisco.com> Signed-off-by: Fabien Thomas <fabien.thomas@smile.fr> Signed-off-by: Paul Barker <paul@pbarker.dev>
This commit is contained in:
committed by
Paul Barker
parent
2b8eb621c1
commit
12c7c6841f
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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) {
|
||||
@@ -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) {
|
||||
@@ -73,6 +73,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/"
|
||||
|
||||
Reference in New Issue
Block a user