Skip to content

Fix use-after-free of pyState at process exit on Linux - #36

Open
SamiAGOURRAM wants to merge 1 commit into
StephenSmith25:masterfrom
SamiAGOURRAM:fix/exit-order-pystate
Open

SamiAGOURRAM wants to merge 1 commit into
StephenSmith25:masterfrom
SamiAGOURRAM:fix/exit-order-pystate

Conversation

@SamiAGOURRAM

Copy link
Copy Markdown

Fixes #35.

At process exit on Linux, glibc runs the C++ static destructors (__run_exit_handlers) before the libraries' destructor functions (_dl_fini). The namespace-scope std::shared_ptr<PyState> pyState is therefore already destroyed when onLibraryUnload → finalizePythonInterpreter assigns it nullptr, and that assignment decrements a reference count in freed memory.

This change keeps the state and its mutex in objects that are allocated once and never destroyed (function-local static pointers), so finalizePythonInterpreter always resets a live shared_ptr; it also takes the mutex, as instantiation does. Nothing else changes; the Windows DllMain path is untouched.

Checked:

At exit, glibc runs the C++ static destructors (__run_exit_handlers)
before the libraries' destructor functions (_dl_fini). The
namespace-scope shared_ptr pyState was therefore already destroyed when
onLibraryUnload -> finalizePythonInterpreter assigned it nullptr, and
that assignment decremented a reference count in freed memory,
corrupting the heap (glibc could then abort in a later free).

Keep the state and its mutex in objects that are allocated once and
never destroyed, reached through function-local static pointers, so
finalizePythonInterpreter always resets a live shared_ptr. It also takes
the mutex, as instantiation does.
@StephenSmith25

Copy link
Copy Markdown
Owner

I'll look at this by tomorrow but thanks for reporting the issue and fixing it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants