diff mbox series

[whinlatter,1/3] expat: Fix CVE-2026-32776

Message ID 20260322100637.665990-1-deeratho@cisco.com
State New
Headers show
Series [whinlatter,1/3] expat: Fix CVE-2026-32776 | expand

Commit Message

From: Deepak Rathore <deeratho@cisco.com>

Pick the patch [1] as mentioned in [2].

[1] https://github.com/libexpat/libexpat/commit/5be25657583ea91b09025c858b4785834c20f59c
[2] https://security-tracker.debian.org/tracker/CVE-2026-32776

Signed-off-by: Deepak Rathore <deeratho@cisco.com>
diff mbox series

Patch

diff --git a/meta/recipes-core/expat/expat/CVE-2026-32776.patch b/meta/recipes-core/expat/expat/CVE-2026-32776.patch
new file mode 100644
index 0000000000..357c41a763
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-32776.patch
@@ -0,0 +1,90 @@ 
+From dfc050e8c22c40a709a824573efd8691194c1469 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.
+
+CVE: CVE-2026-32776
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/5be25657583ea91b09025c858b4785834c20f59c]
+
+(cherry picked from commit 5be25657583ea91b09025c858b4785834c20f59c)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ 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 a187a3a1..10297c9a 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -6780,7 +6780,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 0231e094..8be3492d 100644
+--- a/tests/basic_tests.c
++++ b/tests/basic_tests.c
+@@ -6213,6 +6213,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");
+@@ -6458,6 +6476,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.51.0
diff --git a/meta/recipes-core/expat/expat_2.7.4.bb b/meta/recipes-core/expat/expat_2.7.4.bb
index 95a1ed52c4..a1cbf77ae1 100644
--- a/meta/recipes-core/expat/expat_2.7.4.bb
+++ b/meta/recipes-core/expat/expat_2.7.4.bb
@@ -10,6 +10,7 @@  VERSION_TAG = "${@d.getVar('PV').replace('.', '_')}"
 
 SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2  \
            file://run-ptest \
+           file://CVE-2026-32776.patch \
            "
 
 GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"