-
-
Notifications
You must be signed in to change notification settings - Fork 34.1k
Open
Labels
3.14bugs and security fixesbugs and security fixes3.15new features, bugs and security fixesnew features, bugs and security fixesextension-modulesC modules in the Modules dirC modules in the Modules dirtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
Bug description
atexit_register() in Modules/atexitmodule.c leaks memory on every call. PyTuple_GetSlice() returns a new reference, but the result is never decref'd after being packed into the callback tuple via PyTuple_Pack().
Additionally, there is no NULL check after PyTuple_GetSlice(), which could lead to undefined behavior if the allocation fails.
// Modules/atexitmodule.c, atexit_register()
PyObject *func_args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
// BUG 1: missing NULL check
PyObject *func_kwargs = kwargs;
...
PyObject *callback = PyTuple_Pack(3, func, func_args, func_kwargs);
// BUG 2: missing Py_DECREF(func_args) — leaks the tupleThe leak is detected by AddressSanitizer/LeakSanitizer when running test_atexit on an ASAN build, causing 3 test failures: test_shutdown, test_atexit_instances, and test_general (subprocess exits with code 1 due to LSAN reporting 240 bytes leaked in 4 allocations).
Fix:
PyObject *func_args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
if (func_args == NULL) {
return NULL;
}
...
PyObject *callback = PyTuple_Pack(3, func, func_args, func_kwargs);
Py_DECREF(func_args);CPython versions tested on
CPython main branch
Operating systems tested on
Linux
Linked PRs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
3.14bugs and security fixesbugs and security fixes3.15new features, bugs and security fixesnew features, bugs and security fixesextension-modulesC modules in the Modules dirC modules in the Modules dirtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error