]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-140824: Fix _Py_DumpExtensionModules() to ignore sub-modules (#144339)
authorVictor Stinner <vstinner@python.org>
Wed, 4 Feb 2026 15:06:35 +0000 (16:06 +0100)
committerGitHub <noreply@github.com>
Wed, 4 Feb 2026 15:06:35 +0000 (16:06 +0100)
Ignore "math.integer" extension if "math" is in
sys.stdlib_module_names.

Lib/test/test_faulthandler.py
Misc/NEWS.d/next/Library/2026-01-30-13-23-06.gh-issue-140824.J1OCrC.rst [new file with mode: 0644]
Python/pylifecycle.c

index 874f52af857b94761ca43c0904ff22f44d5ea4cd..5e88ae47775dbd189ff745b18a127345b2f140af 100644 (file)
@@ -388,10 +388,11 @@ class FaultHandlerTests(unittest.TestCase):
 
     @skip_segfault_on_android
     def test_dump_ext_modules(self):
+        # Don't filter stdlib module names: disable sys.stdlib_module_names
         code = """
             import faulthandler
             import sys
-            # Don't filter stdlib module names
+            import math
             sys.stdlib_module_names = frozenset()
             faulthandler.enable()
             faulthandler._sigsegv()
@@ -403,9 +404,21 @@ class FaultHandlerTests(unittest.TestCase):
         if not match:
             self.fail(f"Cannot find 'Extension modules:' in {stderr!r}")
         modules = set(match.group(1).strip().split(', '))
-        for name in ('sys', 'faulthandler'):
+        for name in ('sys', 'faulthandler', 'math'):
             self.assertIn(name, modules)
 
+        # Ignore "math.integer" sub-module if "math" package is
+        # in sys.stdlib_module_names
+        code = """
+            import faulthandler
+            import math.integer
+            faulthandler.enable()
+            faulthandler._sigsegv()
+            """
+        stderr, exitcode = self.get_output(code)
+        stderr = '\n'.join(stderr)
+        self.assertNotIn('Extension modules:', stderr)
+
     def test_is_enabled(self):
         orig_stderr = sys.stderr
         try:
diff --git a/Misc/NEWS.d/next/Library/2026-01-30-13-23-06.gh-issue-140824.J1OCrC.rst b/Misc/NEWS.d/next/Library/2026-01-30-13-23-06.gh-issue-140824.J1OCrC.rst
new file mode 100644 (file)
index 0000000..dd90b6a
--- /dev/null
@@ -0,0 +1,2 @@
+When :mod:`faulthandler` dumps the list of third-party extension modules,
+ignore sub-modules of stdlib packages. Patch by Victor Stinner.
index d3ed08de1d15d38a287f00920d1fa9f79798f3ed..bb51f8d191c1c3b27b02b8bbe3a3d50f76352161 100644 (file)
@@ -3393,11 +3393,25 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
             Py_hash_t hash;
             // if stdlib_module_names is not NULL, it is always a frozenset.
             while (_PySet_NextEntry(stdlib_module_names, &i, &item, &hash)) {
-                if (PyUnicode_Check(item)
-                    && PyUnicode_Compare(key, item) == 0)
-                {
-                    is_stdlib_ext = 1;
-                    break;
+                if (!PyUnicode_Check(item)) {
+                    continue;
+                }
+                Py_ssize_t len = PyUnicode_GET_LENGTH(item);
+                if (PyUnicode_Tailmatch(key, item, 0, len, -1) == 1) {
+                    Py_ssize_t key_len = PyUnicode_GET_LENGTH(key);
+                    if (key_len == len) {
+                        is_stdlib_ext = 1;
+                        break;
+                    }
+                    assert(key_len > len);
+
+                    // Ignore sub-modules of stdlib packages. For example,
+                    // ignore "math.integer" if key starts with "math.".
+                    Py_UCS4 ch = PyUnicode_ReadChar(key, len);
+                    if (ch == '.') {
+                        is_stdlib_ext = 1;
+                        break;
+                    }
                 }
             }
             if (is_stdlib_ext) {