summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/recipes-core/expat/expat/CVE-2024-8176-03.patch35
-rw-r--r--meta/recipes-core/expat/expat/CVE-2024-8176-04.patch115
-rw-r--r--meta/recipes-core/expat/expat/CVE-2024-8176-05.patch78
-rw-r--r--meta/recipes-core/expat/expat_2.6.4.bb3
4 files changed, 231 insertions, 0 deletions
diff --git a/meta/recipes-core/expat/expat/CVE-2024-8176-03.patch b/meta/recipes-core/expat/expat/CVE-2024-8176-03.patch
new file mode 100644
index 0000000000..c9990d5547
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2024-8176-03.patch
@@ -0,0 +1,35 @@
1From ba80428c2207259103b73871d447dee34755340c Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@tum.de>
3Date: Tue, 23 Sep 2025 11:22:14 +0200
4Subject: [PATCH] lib: Fix detection of asynchronous tags in entities
5
6According to the XML standard, tags must be closed within the same
7element in which they are opened. Since the change of the entity
8processing method in version 2.7.0, violations of this rule have not
9been handled correctly for entities.
10
11This commit adds the required checks to detect any violations and
12restores the correct behaviour.
13
14CVE: CVE-2024-8176
15Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1059]
16Signed-off-by: Peter Marko <peter.marko@siemens.com>
17---
18 lib/xmlparse.c | 4 ++++
19 1 file changed, 4 insertions(+)
20
21diff --git a/lib/xmlparse.c b/lib/xmlparse.c
22index ce29ab6f..ba4e3c48 100644
23--- a/lib/xmlparse.c
24+++ b/lib/xmlparse.c
25@@ -6087,6 +6087,10 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
26 // process its possible inner entities (which are added to the
27 // m_openInternalEntities during doProlog or doContent calls above)
28 entity->hasMore = XML_FALSE;
29+ if (! entity->is_param
30+ && (openEntity->startTagLevel != parser->m_tagLevel)) {
31+ return XML_ERROR_ASYNC_ENTITY;
32+ }
33 triggerReenter(parser);
34 return result;
35 } // End of entity processing, "if" block will return here
diff --git a/meta/recipes-core/expat/expat/CVE-2024-8176-04.patch b/meta/recipes-core/expat/expat/CVE-2024-8176-04.patch
new file mode 100644
index 0000000000..9623467698
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2024-8176-04.patch
@@ -0,0 +1,115 @@
1From 81a114f7eebcd41a6993337128cda337986a26f4 Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Mon, 15 Sep 2025 21:57:07 +0200
4Subject: [PATCH] tests: Cover XML_ERROR_ASYNC_ENTITY cases
5
6CVE: CVE-2024-8176
7Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1059]
8Signed-off-by: Peter Marko <peter.marko@siemens.com>
9---
10 tests/misc_tests.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++
11 1 file changed, 87 insertions(+)
12
13diff --git a/tests/misc_tests.c b/tests/misc_tests.c
14index 3346bce6..19f41df7 100644
15--- a/tests/misc_tests.c
16+++ b/tests/misc_tests.c
17@@ -621,6 +621,91 @@ START_TEST(test_misc_expected_event_ptr_issue_980) {
18 }
19 END_TEST
20
21+START_TEST(test_misc_sync_entity_tolerated) {
22+ const char *const doc = "<!DOCTYPE t0 [\n"
23+ " <!ENTITY a '<t1></t1>'>\n"
24+ " <!ENTITY b '<t2>two</t2>'>\n"
25+ " <!ENTITY c '<t3>three<t4>four</t4>three</t3>'>\n"
26+ " <!ENTITY d '<t5>&b;</t5>'>\n"
27+ "]>\n"
28+ "<t0>&a;&b;&c;&d;</t0>\n";
29+ XML_Parser parser = XML_ParserCreate(NULL);
30+
31+ assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
32+ /*isFinal=*/XML_TRUE)
33+ == XML_STATUS_OK);
34+
35+ XML_ParserFree(parser);
36+}
37+END_TEST
38+
39+START_TEST(test_misc_async_entity_rejected) {
40+ struct test_case {
41+ const char *doc;
42+ enum XML_Status expectedStatusNoGE;
43+ enum XML_Error expectedErrorNoGE;
44+ };
45+ const struct test_case cases[] = {
46+ // Opened by one entity, closed by another
47+ {"<!DOCTYPE t0 [\n"
48+ " <!ENTITY open '<t1>'>\n"
49+ " <!ENTITY close '</t1>'>\n"
50+ "]>\n"
51+ "<t0>&open;&close;</t0>\n",
52+ XML_STATUS_OK, XML_ERROR_NONE},
53+ // Opened by tag, closed by entity (non-root case)
54+ {"<!DOCTYPE t0 [\n"
55+ " <!ENTITY g0 ''>\n"
56+ " <!ENTITY g1 '&g0;</t1>'>\n"
57+ "]>\n"
58+ "<t0><t1>&g1;</t0>\n",
59+ XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH},
60+ // Opened by tag, closed by entity (root case)
61+ {"<!DOCTYPE t0 [\n"
62+ " <!ENTITY g0 ''>\n"
63+ " <!ENTITY g1 '&g0;</t0>'>\n"
64+ "]>\n"
65+ "<t0>&g1;\n",
66+ XML_STATUS_ERROR, XML_ERROR_NO_ELEMENTS},
67+ // Opened by entity, closed by tag <-- regression from 2.7.0
68+ {"<!DOCTYPE t0 [\n"
69+ " <!ENTITY g0 ''>\n"
70+ " <!ENTITY g1 '<t1>&g0;'>\n"
71+ "]>\n"
72+ "<t0>&g1;</t1></t0>\n",
73+ XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH},
74+ // Opened by tag, closed by entity; then the other way around
75+ {"<!DOCTYPE t0 [\n"
76+ " <!ENTITY open '<t1>'>\n"
77+ " <!ENTITY close '</t1>'>\n"
78+ "]>\n"
79+ "<t0><t1>&close;&open;</t1></t0>\n",
80+ XML_STATUS_OK, XML_ERROR_NONE},
81+ };
82+
83+ for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
84+ const struct test_case testCase = cases[i];
85+ set_subtest("cases[%d]", (int)i);
86+
87+ const char *const doc = testCase.doc;
88+#if XML_GE == 1
89+ const enum XML_Status expectedStatus = XML_STATUS_ERROR;
90+ const enum XML_Error expectedError = XML_ERROR_ASYNC_ENTITY;
91+#else
92+ const enum XML_Status expectedStatus = testCase.expectedStatusNoGE;
93+ const enum XML_Error expectedError = testCase.expectedErrorNoGE;
94+#endif
95+
96+ XML_Parser parser = XML_ParserCreate(NULL);
97+ assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
98+ /*isFinal=*/XML_TRUE)
99+ == expectedStatus);
100+ assert_true(XML_GetErrorCode(parser) == expectedError);
101+ XML_ParserFree(parser);
102+ }
103+}
104+END_TEST
105+
106 void
107 make_miscellaneous_test_case(Suite *s) {
108 TCase *tc_misc = tcase_create("miscellaneous tests");
109@@ -649,4 +734,6 @@ make_miscellaneous_test_case(Suite *s) {
110 tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
111 tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content);
112 tcase_add_test(tc_misc, test_misc_expected_event_ptr_issue_980);
113+ tcase_add_test(tc_misc, test_misc_sync_entity_tolerated);
114+ tcase_add_test(tc_misc, test_misc_async_entity_rejected);
115 }
diff --git a/meta/recipes-core/expat/expat/CVE-2024-8176-05.patch b/meta/recipes-core/expat/expat/CVE-2024-8176-05.patch
new file mode 100644
index 0000000000..063a590a11
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2024-8176-05.patch
@@ -0,0 +1,78 @@
1From a9aaf85cfc3025b7013b5adc4bef2ce32ecc7fb1 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@tum.de>
3Date: Tue, 23 Sep 2025 12:12:50 +0200
4Subject: [PATCH] tests: Add line/column checks to async entity tests
5
6CVE: CVE-2024-8176
7Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1059]
8Signed-off-by: Peter Marko <peter.marko@siemens.com>
9---
10 tests/misc_tests.c | 17 ++++++++++++-----
11 1 file changed, 12 insertions(+), 5 deletions(-)
12
13diff --git a/tests/misc_tests.c b/tests/misc_tests.c
14index 19f41df7..7a4d2455 100644
15--- a/tests/misc_tests.c
16+++ b/tests/misc_tests.c
17@@ -644,6 +644,8 @@ START_TEST(test_misc_async_entity_rejected) {
18 const char *doc;
19 enum XML_Status expectedStatusNoGE;
20 enum XML_Error expectedErrorNoGE;
21+ XML_Size expectedErrorLine;
22+ XML_Size expectedErrorColumn;
23 };
24 const struct test_case cases[] = {
25 // Opened by one entity, closed by another
26@@ -652,35 +654,35 @@ START_TEST(test_misc_async_entity_rejected) {
27 " <!ENTITY close '</t1>'>\n"
28 "]>\n"
29 "<t0>&open;&close;</t0>\n",
30- XML_STATUS_OK, XML_ERROR_NONE},
31+ XML_STATUS_OK, XML_ERROR_NONE, 5, 4},
32 // Opened by tag, closed by entity (non-root case)
33 {"<!DOCTYPE t0 [\n"
34 " <!ENTITY g0 ''>\n"
35 " <!ENTITY g1 '&g0;</t1>'>\n"
36 "]>\n"
37 "<t0><t1>&g1;</t0>\n",
38- XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH},
39+ XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH, 5, 8},
40 // Opened by tag, closed by entity (root case)
41 {"<!DOCTYPE t0 [\n"
42 " <!ENTITY g0 ''>\n"
43 " <!ENTITY g1 '&g0;</t0>'>\n"
44 "]>\n"
45 "<t0>&g1;\n",
46- XML_STATUS_ERROR, XML_ERROR_NO_ELEMENTS},
47+ XML_STATUS_ERROR, XML_ERROR_NO_ELEMENTS, 5, 4},
48 // Opened by entity, closed by tag <-- regression from 2.7.0
49 {"<!DOCTYPE t0 [\n"
50 " <!ENTITY g0 ''>\n"
51 " <!ENTITY g1 '<t1>&g0;'>\n"
52 "]>\n"
53 "<t0>&g1;</t1></t0>\n",
54- XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH},
55+ XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH, 5, 4},
56 // Opened by tag, closed by entity; then the other way around
57 {"<!DOCTYPE t0 [\n"
58 " <!ENTITY open '<t1>'>\n"
59 " <!ENTITY close '</t1>'>\n"
60 "]>\n"
61 "<t0><t1>&close;&open;</t1></t0>\n",
62- XML_STATUS_OK, XML_ERROR_NONE},
63+ XML_STATUS_OK, XML_ERROR_NONE, 5, 8},
64 };
65
66 for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
67@@ -701,6 +703,11 @@ START_TEST(test_misc_async_entity_rejected) {
68 /*isFinal=*/XML_TRUE)
69 == expectedStatus);
70 assert_true(XML_GetErrorCode(parser) == expectedError);
71+#if XML_GE == 1
72+ assert_true(XML_GetCurrentLineNumber(parser) == testCase.expectedErrorLine);
73+ assert_true(XML_GetCurrentColumnNumber(parser)
74+ == testCase.expectedErrorColumn);
75+#endif
76 XML_ParserFree(parser);
77 }
78 }
diff --git a/meta/recipes-core/expat/expat_2.6.4.bb b/meta/recipes-core/expat/expat_2.6.4.bb
index ab0b1d54c1..816beaa8a3 100644
--- a/meta/recipes-core/expat/expat_2.6.4.bb
+++ b/meta/recipes-core/expat/expat_2.6.4.bb
@@ -13,6 +13,9 @@ SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \
13 file://0001-tests-Cover-indirect-entity-recursion.patch;striplevel=2 \ 13 file://0001-tests-Cover-indirect-entity-recursion.patch;striplevel=2 \
14 file://CVE-2024-8176-01.patch;striplevel=2 \ 14 file://CVE-2024-8176-01.patch;striplevel=2 \
15 file://CVE-2024-8176-02.patch;striplevel=2 \ 15 file://CVE-2024-8176-02.patch;striplevel=2 \
16 file://CVE-2024-8176-03.patch \
17 file://CVE-2024-8176-04.patch \
18 file://CVE-2024-8176-05.patch \
16 " 19 "
17 20
18GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/" 21GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"