-
Notifications
You must be signed in to change notification settings - Fork 607
Expand file tree
/
Copy pathCVE-2026-32776.patch
More file actions
88 lines (81 loc) · 3.34 KB
/
CVE-2026-32776.patch
File metadata and controls
88 lines (81 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
From 90376a0668e575098017898c4ab54d6d5e3d0451 Mon Sep 17 00:00:00 2001
From: Francesco Bertolaccini <francesco.bertolaccini@trailofbits.com>
Date: Tue, 3 Mar 2026 16:41:43 +0100
Subject: [PATCH] Fix NULL function-pointer dereference for empty external
parameter entities
When an external parameter entity with empty text is referenced inside
an entity declaration value, the sub-parser created to handle it receives
0 bytes of input. Processing enters entityValueInitProcessor which calls
storeEntityValue() with the parser's encoding; since no bytes were ever
processed, encoding detection has not yet occurred and the encoding is
still the initial probing encoding set up by XmlInitEncoding(). That
encoding only populates scanners[] (for prolog and content), not
literalScanners[]. XmlEntityValueTok() calls through
literalScanners[XML_ENTITY_VALUE_LITERAL] which is NULL, causing a
SEGV.
Skip the tokenization loop entirely when entityTextPtr >= entityTextEnd,
and initialize the `next` pointer before the early exit so that callers
(callStoreEntityValue) receive a valid value through nextPtr.
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/libexpat/libexpat/pull/1158.patch
---
lib/xmlparse.c | 9 ++++++++-
tests/basic_tests.c | 19 +++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 0bf913c..d126f5b 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -6765,7 +6765,14 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
return XML_ERROR_NO_MEMORY;
}
- const char *next;
+ const char *next = entityTextPtr;
+
+ /* Nothing to tokenize. */
+ if (entityTextPtr >= entityTextEnd) {
+ result = XML_ERROR_NONE;
+ goto endEntityValue;
+ }
+
for (;;) {
next
= entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
diff --git a/tests/basic_tests.c b/tests/basic_tests.c
index 2db2a76..cfb09f3 100644
--- a/tests/basic_tests.c
+++ b/tests/basic_tests.c
@@ -6123,6 +6123,24 @@ START_TEST(test_varying_buffer_fills) {
}
END_TEST
+START_TEST(test_empty_ext_param_entity_in_value) {
+ const char *text = "<!DOCTYPE r SYSTEM \"ext.dtd\"><r/>";
+ ExtOption options[] = {
+ {XCS("ext.dtd"), "<!ENTITY % pe SYSTEM \"empty\">"
+ "<!ENTITY ge \"%pe;\">"},
+ {XCS("empty"), ""},
+ {NULL, NULL},
+ };
+
+ XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
+ XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
+ XML_SetUserData(g_parser, options);
+ if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(g_parser);
+}
+END_TEST
+
void
make_basic_test_case(Suite *s) {
TCase *tc_basic = tcase_create("basic tests");
@@ -6368,6 +6386,7 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_empty_element_abort);
tcase_add_test__ifdef_xml_dtd(tc_basic,
test_pool_integrity_with_unfinished_attr);
+ tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_ext_param_entity_in_value);
tcase_add_test__if_xml_ge(tc_basic, test_entity_ref_no_elements);
tcase_add_test__if_xml_ge(tc_basic, test_deep_nested_entity);
tcase_add_test__if_xml_ge(tc_basic, test_deep_nested_attribute_entity);
--
2.45.4