Skip to content

Memory leak in atexit.register(): missing Py_DECREF for func_args tuple #144986

@ashm-dev

Description

@ashm-dev

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 tuple

The 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.14bugs and security fixes3.15new features, bugs and security fixesextension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions