https://github.com/python/cpython/commit/3d7091e69d7fb6fa9c49296e4295d7386940e58e
commit: 3d7091e69d7fb6fa9c49296e4295d7386940e58e
branch: 3.10
author: Stan Ulbrych <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-04-08T11:27:21+01:00
summary:

[3.10] gh-146083: Upgrade bundled Expat to 2.7.5 (GH-146085) (#146608)

(cherry picked from commit e39d84a37dfc8bcdc0eb4d6f3ce7d5ee829d7f30)

files:
A Misc/NEWS.d/next/Library/2026-03-17-20-52-24.gh-issue-146083.NxZa_c.rst
M Modules/expat/expat.h
M Modules/expat/expat_external.h
M Modules/expat/refresh.sh
M Modules/expat/xmlparse.c
M Modules/expat/xmlrole.c
M Modules/expat/xmltok.c
M Modules/expat/xmltok_ns.c

diff --git 
a/Misc/NEWS.d/next/Library/2026-03-17-20-52-24.gh-issue-146083.NxZa_c.rst 
b/Misc/NEWS.d/next/Library/2026-03-17-20-52-24.gh-issue-146083.NxZa_c.rst
new file mode 100644
index 00000000000000..6805a40a03e734
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-03-17-20-52-24.gh-issue-146083.NxZa_c.rst
@@ -0,0 +1 @@
+Update bundled `libexpat <https://libexpat.github.io/>`_ to version 2.7.5.
diff --git a/Modules/expat/expat.h b/Modules/expat/expat.h
index 6c7c4186927725..18dbaebde293bc 100644
--- a/Modules/expat/expat.h
+++ b/Modules/expat/expat.h
@@ -1082,7 +1082,7 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool 
enabled);
 */
 #  define XML_MAJOR_VERSION 2
 #  define XML_MINOR_VERSION 7
-#  define XML_MICRO_VERSION 4
+#  define XML_MICRO_VERSION 5
 
 #  ifdef __cplusplus
 }
diff --git a/Modules/expat/expat_external.h b/Modules/expat/expat_external.h
index 6f3f3c48ce9cff..cf4d445e68b00c 100644
--- a/Modules/expat/expat_external.h
+++ b/Modules/expat/expat_external.h
@@ -12,7 +12,7 @@
    Copyright (c) 2001-2002 Greg Stein <[email protected]>
    Copyright (c) 2002-2006 Karl Waclawek <[email protected]>
    Copyright (c) 2016      Cristian Rodríguez <[email protected]>
-   Copyright (c) 2016-2025 Sebastian Pipping <[email protected]>
+   Copyright (c) 2016-2026 Sebastian Pipping <[email protected]>
    Copyright (c) 2017      Rhodri James <[email protected]>
    Copyright (c) 2018      Yury Gribov <[email protected]>
    Licensed under the MIT license:
diff --git a/Modules/expat/refresh.sh b/Modules/expat/refresh.sh
index a3bf7d7d172bc5..663cceba5e9d16 100755
--- a/Modules/expat/refresh.sh
+++ b/Modules/expat/refresh.sh
@@ -12,9 +12,9 @@ fi
 
 # Update this when updating to a new version after verifying that the changes
 # the update brings in are good. These values are used for verifying the SBOM, 
too.
-expected_libexpat_tag="R_2_7_4"
-expected_libexpat_version="2.7.4"
-expected_libexpat_sha256="461ecc8aa98ab1a68c2db788175665d1a4db640dc05bf0e289b6ea17122144ec"
+expected_libexpat_tag="R_2_7_5"
+expected_libexpat_version="2.7.5"
+expected_libexpat_sha256="9931f9860d18e6cf72d183eb8f309bfb96196c00e1d40caa978e95bc9aa978b6"
 
 expat_dir="$(realpath "$(dirname -- "${BASH_SOURCE[0]}")")"
 cd ${expat_dir}
diff --git a/Modules/expat/xmlparse.c b/Modules/expat/xmlparse.c
index 086fca59112ee1..0248b6651ffbff 100644
--- a/Modules/expat/xmlparse.c
+++ b/Modules/expat/xmlparse.c
@@ -1,4 +1,4 @@
-/* fab937ab8b186d7d296013669c332e6dfce2f99567882cff1f8eb24223c524a7 (2.7.4+)
+/* 93c1caa66e2b0310459482516af05505b57c5cb7b96df777105308fc585c85d1 (2.7.5+)
                             __  __            _
                          ___\ \/ /_ __   __ _| |_
                         / _ \\  /| '_ \ / _` | __|
@@ -590,6 +590,8 @@ static XML_Char *poolStoreString(STRING_POOL *pool, const 
ENCODING *enc,
 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
 static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
                                                const XML_Char *s);
+static const XML_Char *FASTCALL poolCopyStringNoFinish(STRING_POOL *pool,
+                                                       const XML_Char *s);
 static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
                                        int n);
 static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
@@ -5086,7 +5088,7 @@ entityValueInitProcessor(XML_Parser parser, const char 
*s, const char *end,
     }
     /* If we get this token, we have the start of what might be a
        normal tag, but not a declaration (i.e. it doesn't begin with
-       "<!").  In a DTD context, that isn't legal.
+       "<!" or "<?").  In a DTD context, that isn't legal.
     */
     else if (tok == XML_TOK_INSTANCE_START) {
       *nextPtr = next;
@@ -5175,6 +5177,15 @@ entityValueProcessor(XML_Parser parser, const char *s, 
const char *end,
       /* found end of entity value - can store it now */
       return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT, NULL);
     }
+    /* If we get this token, we have the start of what might be a
+       normal tag, but not a declaration (i.e. it doesn't begin with
+       "<!" or "<?").  In a DTD context, that isn't legal.
+    */
+    else if (tok == XML_TOK_INSTANCE_START) {
+      *nextPtr = next;
+      return XML_ERROR_SYNTAX;
+    }
+
     start = next;
   }
 }
@@ -6789,7 +6800,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 
*/
@@ -7439,16 +7457,24 @@ setContext(XML_Parser parser, const XML_Char *context) {
       else {
         if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
           return XML_FALSE;
-        prefix
-            = (PREFIX *)lookup(parser, &dtd->prefixes,
-                               poolStart(&parser->m_tempPool), sizeof(PREFIX));
-        if (! prefix)
+        const XML_Char *const prefixName = poolCopyStringNoFinish(
+            &dtd->pool, poolStart(&parser->m_tempPool));
+        if (! prefixName) {
           return XML_FALSE;
-        if (prefix->name == poolStart(&parser->m_tempPool)) {
-          prefix->name = poolCopyString(&dtd->pool, prefix->name);
-          if (! prefix->name)
-            return XML_FALSE;
         }
+
+        prefix = (PREFIX *)lookup(parser, &dtd->prefixes, prefixName,
+                                  sizeof(PREFIX));
+
+        const bool prefixNameUsed = prefix && prefix->name == prefixName;
+        if (prefixNameUsed)
+          poolFinish(&dtd->pool);
+        else
+          poolDiscard(&dtd->pool);
+
+        if (! prefix)
+          return XML_FALSE;
+
         poolDiscard(&parser->m_tempPool);
       }
       for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0');
@@ -8036,6 +8062,23 @@ poolCopyString(STRING_POOL *pool, const XML_Char *s) {
   return s;
 }
 
+// A version of `poolCopyString` that does not call `poolFinish`
+// and reverts any partial advancement upon failure.
+static const XML_Char *FASTCALL
+poolCopyStringNoFinish(STRING_POOL *pool, const XML_Char *s) {
+  const XML_Char *const original = s;
+  do {
+    if (! poolAppendChar(pool, *s)) {
+      // Revert any previously successful advancement
+      const ptrdiff_t advancedBy = s - original;
+      if (advancedBy > 0)
+        pool->ptr -= advancedBy;
+      return NULL;
+    }
+  } while (*s++);
+  return pool->start;
+}
+
 static const XML_Char *
 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) {
   if (! pool->ptr && ! poolGrow(pool)) {
diff --git a/Modules/expat/xmlrole.c b/Modules/expat/xmlrole.c
index d56bee82dd2d13..b1dfb456e5df87 100644
--- a/Modules/expat/xmlrole.c
+++ b/Modules/expat/xmlrole.c
@@ -12,7 +12,7 @@
    Copyright (c) 2002-2006 Karl Waclawek <[email protected]>
    Copyright (c) 2002-2003 Fred L. Drake, Jr. <[email protected]>
    Copyright (c) 2005-2009 Steven Solie <[email protected]>
-   Copyright (c) 2016-2023 Sebastian Pipping <[email protected]>
+   Copyright (c) 2016-2026 Sebastian Pipping <[email protected]>
    Copyright (c) 2017      Rhodri James <[email protected]>
    Copyright (c) 2019      David Loffredo <[email protected]>
    Copyright (c) 2021      Donghee Na <[email protected]>
diff --git a/Modules/expat/xmltok.c b/Modules/expat/xmltok.c
index 32cd5f147e9322..f6e5f742c928c8 100644
--- a/Modules/expat/xmltok.c
+++ b/Modules/expat/xmltok.c
@@ -12,7 +12,7 @@
    Copyright (c) 2002      Greg Stein <[email protected]>
    Copyright (c) 2002-2016 Karl Waclawek <[email protected]>
    Copyright (c) 2005-2009 Steven Solie <[email protected]>
-   Copyright (c) 2016-2024 Sebastian Pipping <[email protected]>
+   Copyright (c) 2016-2026 Sebastian Pipping <[email protected]>
    Copyright (c) 2016      Pascal Cuoq <[email protected]>
    Copyright (c) 2016      Don Lewis <[email protected]>
    Copyright (c) 2017      Rhodri James <[email protected]>
diff --git a/Modules/expat/xmltok_ns.c b/Modules/expat/xmltok_ns.c
index 810ca2c6d0485e..1cd60de1e4fe51 100644
--- a/Modules/expat/xmltok_ns.c
+++ b/Modules/expat/xmltok_ns.c
@@ -11,7 +11,7 @@
    Copyright (c) 2002      Greg Stein <[email protected]>
    Copyright (c) 2002      Fred L. Drake, Jr. <[email protected]>
    Copyright (c) 2002-2006 Karl Waclawek <[email protected]>
-   Copyright (c) 2017-2021 Sebastian Pipping <[email protected]>
+   Copyright (c) 2017-2026 Sebastian Pipping <[email protected]>
    Copyright (c) 2025      Alfonso Gregory <[email protected]>
    Licensed under the MIT license:
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to