From 7e35240dc97e9fd4f609e31f27c27b659535e436 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Thu, 11 Sep 2025 00:27:05 +0200
Subject: [PATCH] lib: Exclude the content model from allocation tracking

.. so that applications that are not using XML_FreeContentModel
but plain free(..) or .free_fcn() to free the content model's
memory are safe

CVE: CVE-2025-59375
Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/7e35240dc97e9fd4f609e31f27c27b659535e436]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
 lib/xmlparse.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 00139b94..d0b6e0cd 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -2785,7 +2785,10 @@ void XMLCALL
 XML_FreeContentModel(XML_Parser parser, XML_Content *model) {
   if (parser == NULL)
     return;
-  FREE(parser, model);
+
+  // NOTE: We are avoiding FREE(..) here because the content model
+  //       has been created using plain .malloc_fcn(..) rather than MALLOC(..).
+  parser->m_mem.free_fcn(model);
 }
 
 void *XMLCALL
@@ -6063,8 +6066,12 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
     case XML_ROLE_CONTENT_EMPTY:
       if (dtd->in_eldecl) {
         if (parser->m_elementDeclHandler) {
+          // NOTE: We are avoiding MALLOC(..) here to so that
+          //       applications that are not using XML_FreeContentModel but
+          //       plain free(..) or .free_fcn() to free the content model's
+          //       memory are safe.
           XML_Content *content
-              = (XML_Content *)MALLOC(parser, sizeof(XML_Content));
+              = (XML_Content *)parser->m_mem.malloc_fcn(sizeof(XML_Content));
           if (! content)
             return XML_ERROR_NO_MEMORY;
           content->quant = XML_CQUANT_NONE;
@@ -8278,7 +8285,10 @@ build_model(XML_Parser parser) {
   const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content)
                             + (dtd->contentStringLen * sizeof(XML_Char)));
 
-  ret = (XML_Content *)MALLOC(parser, allocsize);
+  // NOTE: We are avoiding MALLOC(..) here to so that
+  //       applications that are not using XML_FreeContentModel but plain
+  //       free(..) or .free_fcn() to free the content model's memory are safe.
+  ret = (XML_Content *)parser->m_mem.malloc_fcn(allocsize);
   if (! ret)
     return NULL;
 
