Skip to content

Commit 2aea861

Browse files
authored
gh-140824: Fix _Py_DumpExtensionModules() to ignore sub-modules (#144339)
Ignore "math.integer" extension if "math" is in sys.stdlib_module_names.
1 parent 0bb4eca commit 2aea861

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

Lib/test/test_faulthandler.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,10 +388,11 @@ def test_disable(self):
388388

389389
@skip_segfault_on_android
390390
def test_dump_ext_modules(self):
391+
# Don't filter stdlib module names: disable sys.stdlib_module_names
391392
code = """
392393
import faulthandler
393394
import sys
394-
# Don't filter stdlib module names
395+
import math
395396
sys.stdlib_module_names = frozenset()
396397
faulthandler.enable()
397398
faulthandler._sigsegv()
@@ -403,9 +404,21 @@ def test_dump_ext_modules(self):
403404
if not match:
404405
self.fail(f"Cannot find 'Extension modules:' in {stderr!r}")
405406
modules = set(match.group(1).strip().split(', '))
406-
for name in ('sys', 'faulthandler'):
407+
for name in ('sys', 'faulthandler', 'math'):
407408
self.assertIn(name, modules)
408409

410+
# Ignore "math.integer" sub-module if "math" package is
411+
# in sys.stdlib_module_names
412+
code = """
413+
import faulthandler
414+
import math.integer
415+
faulthandler.enable()
416+
faulthandler._sigsegv()
417+
"""
418+
stderr, exitcode = self.get_output(code)
419+
stderr = '\n'.join(stderr)
420+
self.assertNotIn('Extension modules:', stderr)
421+
409422
def test_is_enabled(self):
410423
orig_stderr = sys.stderr
411424
try:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
When :mod:`faulthandler` dumps the list of third-party extension modules,
2+
ignore sub-modules of stdlib packages. Patch by Victor Stinner.

Python/pylifecycle.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3393,11 +3393,25 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp)
33933393
Py_hash_t hash;
33943394
// if stdlib_module_names is not NULL, it is always a frozenset.
33953395
while (_PySet_NextEntry(stdlib_module_names, &i, &item, &hash)) {
3396-
if (PyUnicode_Check(item)
3397-
&& PyUnicode_Compare(key, item) == 0)
3398-
{
3399-
is_stdlib_ext = 1;
3400-
break;
3396+
if (!PyUnicode_Check(item)) {
3397+
continue;
3398+
}
3399+
Py_ssize_t len = PyUnicode_GET_LENGTH(item);
3400+
if (PyUnicode_Tailmatch(key, item, 0, len, -1) == 1) {
3401+
Py_ssize_t key_len = PyUnicode_GET_LENGTH(key);
3402+
if (key_len == len) {
3403+
is_stdlib_ext = 1;
3404+
break;
3405+
}
3406+
assert(key_len > len);
3407+
3408+
// Ignore sub-modules of stdlib packages. For example,
3409+
// ignore "math.integer" if key starts with "math.".
3410+
Py_UCS4 ch = PyUnicode_ReadChar(key, len);
3411+
if (ch == '.') {
3412+
is_stdlib_ext = 1;
3413+
break;
3414+
}
34013415
}
34023416
}
34033417
if (is_stdlib_ext) {

0 commit comments

Comments
 (0)