Skip to content

Commit 7330b4d

Browse files
authored
expat: Fixed CVE-2026-32778 (#965)
Signed-off-by: Shalini Singhal <shalinix.singhal@intel.com>
1 parent fee6e04 commit 7330b4d

2 files changed

Lines changed: 142 additions & 1 deletion

File tree

SPECS/expat/CVE-2026-32778.patch

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
From 576b61e42feeea704253cb7c7bedb2eeb3754387 Mon Sep 17 00:00:00 2001
2+
From: laserbear <10689391+Laserbear@users.noreply.github.com>
3+
Date: Sun, 8 Mar 2026 17:28:06 -0700
4+
Subject: [PATCH 1/2] copy prefix name to pool before lookup
5+
6+
.. so that we cannot end up with a zombie PREFIX in the pool
7+
that has NULL for a name.
8+
9+
Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
10+
---
11+
lib/xmlparse.c | 43 +++++++++++++++++++++++++++++++++++--------
12+
1 file changed, 35 insertions(+), 8 deletions(-)
13+
14+
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
15+
index 086fca5911..5a49f3f5d7 100644
16+
--- a/lib/xmlparse.c
17+
+++ b/lib/xmlparse.c
18+
@@ -590,6 +590,8 @@ static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
19+
static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
20+
static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
21+
const XML_Char *s);
22+
+static const XML_Char *FASTCALL poolCopyStringNoFinish(STRING_POOL *pool,
23+
+ const XML_Char *s);
24+
static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
25+
int n);
26+
static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
27+
@@ -7439,16 +7441,24 @@ setContext(XML_Parser parser, const XML_Char *context) {
28+
else {
29+
if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
30+
return XML_FALSE;
31+
- prefix
32+
- = (PREFIX *)lookup(parser, &dtd->prefixes,
33+
- poolStart(&parser->m_tempPool), sizeof(PREFIX));
34+
- if (! prefix)
35+
+ const XML_Char *const prefixName = poolCopyStringNoFinish(
36+
+ &dtd->pool, poolStart(&parser->m_tempPool));
37+
+ if (! prefixName) {
38+
return XML_FALSE;
39+
- if (prefix->name == poolStart(&parser->m_tempPool)) {
40+
- prefix->name = poolCopyString(&dtd->pool, prefix->name);
41+
- if (! prefix->name)
42+
- return XML_FALSE;
43+
}
44+
+
45+
+ prefix = (PREFIX *)lookup(parser, &dtd->prefixes, prefixName,
46+
+ sizeof(PREFIX));
47+
+
48+
+ const bool prefixNameUsed = prefix && prefix->name == prefixName;
49+
+ if (prefixNameUsed)
50+
+ poolFinish(&dtd->pool);
51+
+ else
52+
+ poolDiscard(&dtd->pool);
53+
+
54+
+ if (! prefix)
55+
+ return XML_FALSE;
56+
+
57+
poolDiscard(&parser->m_tempPool);
58+
}
59+
for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0');
60+
@@ -8036,6 +8046,23 @@ poolCopyString(STRING_POOL *pool, const XML_Char *s) {
61+
return s;
62+
}
63+
64+
+// A version of `poolCopyString` that does not call `poolFinish`
65+
+// and reverts any partial advancement upon failure.
66+
+static const XML_Char *FASTCALL
67+
+poolCopyStringNoFinish(STRING_POOL *pool, const XML_Char *s) {
68+
+ const XML_Char *const original = s;
69+
+ do {
70+
+ if (! poolAppendChar(pool, *s)) {
71+
+ // Revert any previously successful advancement
72+
+ const ptrdiff_t advancedBy = s - original;
73+
+ if (advancedBy > 0)
74+
+ pool->ptr -= advancedBy;
75+
+ return NULL;
76+
+ }
77+
+ } while (*s++);
78+
+ return pool->start;
79+
+}
80+
+
81+
static const XML_Char *
82+
poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) {
83+
if (! pool->ptr && ! poolGrow(pool)) {
84+
85+
From d5fa769b7a7290a7e2c4a0b2287106dec9b3c030 Mon Sep 17 00:00:00 2001
86+
From: laserbear <10689391+Laserbear@users.noreply.github.com>
87+
Date: Sun, 8 Mar 2026 17:28:06 -0700
88+
Subject: [PATCH 2/2] test that we do not end up with a zombie PREFIX in the
89+
pool
90+
91+
---
92+
tests/nsalloc_tests.c | 27 +++++++++++++++++++++++++++
93+
1 file changed, 27 insertions(+)
94+
95+
diff --git a/tests/nsalloc_tests.c b/tests/nsalloc_tests.c
96+
index 60fa87f834..9e26d4ee14 100644
97+
--- a/tests/nsalloc_tests.c
98+
+++ b/tests/nsalloc_tests.c
99+
@@ -1505,6 +1505,32 @@ START_TEST(test_nsalloc_prefixed_element) {
100+
}
101+
END_TEST
102+
103+
+/* Verify that retry after OOM in setContext() does not crash.
104+
+ */
105+
+START_TEST(test_nsalloc_setContext_zombie) {
106+
+ const char *text = "<doc>Hello</doc>";
107+
+ unsigned int i;
108+
+ const unsigned int max_alloc_count = 30;
109+
+
110+
+ for (i = 0; i < max_alloc_count; i++) {
111+
+ g_allocation_count = (int)i;
112+
+ if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
113+
+ != XML_STATUS_ERROR)
114+
+ break;
115+
+ /* Retry on the same parser — must not crash */
116+
+ g_allocation_count = ALLOC_ALWAYS_SUCCEED;
117+
+ XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE);
118+
+
119+
+ nsalloc_teardown();
120+
+ nsalloc_setup();
121+
+ }
122+
+ if (i == 0)
123+
+ fail("Parsing worked despite failing allocations");
124+
+ else if (i == max_alloc_count)
125+
+ fail("Parsing failed even at maximum allocation count");
126+
+}
127+
+END_TEST
128+
+
129+
void
130+
make_nsalloc_test_case(Suite *s) {
131+
TCase *tc_nsalloc = tcase_create("namespace allocation tests");
132+
@@ -1539,4 +1565,5 @@ make_nsalloc_test_case(Suite *s) {
133+
tcase_add_test__if_xml_ge(tc_nsalloc, test_nsalloc_long_default_in_ext);
134+
tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
135+
tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
136+
+ tcase_add_test(tc_nsalloc, test_nsalloc_setContext_zombie);
137+
}

SPECS/expat/expat.spec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Summary: An XML parser library
33
Name: expat
44
Version: 2.6.4
5-
Release: 4%{?dist}
5+
Release: 5%{?dist}
66
License: MIT
77
Vendor: Intel Corporation
88
Distribution: Edge Microvisor Toolkit
@@ -13,6 +13,7 @@ Patch0: CVE-2024-8176.patch
1313
Patch1: CVE-2025-59375.patch
1414
Patch2: CVE-2026-24515.patch
1515
Patch3: CVE-2026-25210.patch
16+
Patch4: CVE-2026-32778.patch
1617
Requires: %{name}-libs = %{version}-%{release}
1718

1819
BuildRequires: autoconf, libtool, xmlto, gcc-c++
@@ -74,6 +75,9 @@ rm -rf %{buildroot}/%{_docdir}/%{name}
7475
%{_libdir}/libexpat.so.1*
7576

7677
%changelog
78+
* Mon May 11 2026 Shalini Singhal <shalinix.singhal@intel.com> - 2.6.4-5
79+
+ Fix CVE-2026-32778 with a patch
80+
7781
* Thu Jan 8 2025 Lee Chee Yang <chee.yang.lee@intel.com> - 2.6.4-3
7882
- add BuildRequires
7983
- Patch for CVE-2026-25210

0 commit comments

Comments
 (0)