Skip to content

Harden PYBIND11_MODULE_PYINIT and get_internals() against crashes during module init#6018

Merged
rwgk merged 2 commits intopybind:masterfrom
rwgk:ensure_internals_hardening
Mar 29, 2026
Merged

Harden PYBIND11_MODULE_PYINIT and get_internals() against crashes during module init#6018
rwgk merged 2 commits intopybind:masterfrom
rwgk:ensure_internals_hardening

Conversation

@rwgk
Copy link
Copy Markdown
Collaborator

@rwgk rwgk commented Mar 28, 2026

Description

Motivated by the crash reports in #5993 (v3.0.2 regression: access violation in get_internals during module import on Windows / Python 3.10–3.11):

  • Wrap the body of PYBIND11_MODULE_PYINIT (the PyInit_* function) in try / PYBIND11_CATCH_INIT_EXCEPTIONS, matching the pattern already used in PYBIND11_MODULE_EXEC. Previously, any C++ exception thrown by ensure_internals() during phase-1 module init would propagate through the extern "C" PyInit_* boundary — undefined behavior on MSVC that can manifest as an access violation rather than a clean error.

  • Add explicit nullptr guards with pybind11_fail() in get_internals() after get_pp() and create_pp_content_once(), converting silent null-pointer dereferences into actionable error messages.

Suggested changelog entry:

  • Wrapped PYBIND11_MODULE_PYINIT body in try-catch to prevent C++ exceptions from propagating through the extern "C" PyInit_* boundary (undefined behavior on MSVC, could cause access violations instead of clean error messages). Added nullptr guards in get_internals() for improved crash diagnostics.

rwgk added 2 commits March 28, 2026 11:20
Previously, ensure_internals() was called without exception handling
in the PyInit_* function (PYBIND11_MODULE_PYINIT), while the same call
in PYBIND11_MODULE_EXEC was already wrapped in try-catch. On MSVC,
a C++ exception propagating through the extern "C" PyInit_* boundary
is undefined behavior, which can manifest as an access violation
instead of a clean error message. This is a potential contributor to
crashes like pybindgh-5993. Wrap the entire PyInit body in try/catch using
the existing PYBIND11_CATCH_INIT_EXCEPTIONS pattern.

Made-with: Cursor
Add explicit null checks after get_pp() and create_pp_content_once()
in get_internals(), calling pybind11_fail() with descriptive messages.
These guards convert potential null-pointer dereferences (which produce
unhelpful access-violation crashes, especially on Windows) into clear
runtime_error messages that can be caught and reported as ImportError
by the try-catch added in the previous commit.

Made-with: Cursor
@rwgk rwgk requested a review from b-pass March 29, 2026 05:28
Copy link
Copy Markdown
Collaborator

@b-pass b-pass left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

@rwgk rwgk merged commit e8cead1 into pybind:master Mar 29, 2026
89 checks passed
@github-actions github-actions bot added the needs changelog Possibly needs a changelog entry label Mar 29, 2026
@rwgk rwgk deleted the ensure_internals_hardening branch March 29, 2026 15:03
rwgk added a commit to rwgk/pybind11 that referenced this pull request Mar 30, 2026
… during module init (pybind#6018)

* Wrap ensure_internals() in try-catch in PYBIND11_MODULE_PYINIT

Previously, ensure_internals() was called without exception handling
in the PyInit_* function (PYBIND11_MODULE_PYINIT), while the same call
in PYBIND11_MODULE_EXEC was already wrapped in try-catch. On MSVC,
a C++ exception propagating through the extern "C" PyInit_* boundary
is undefined behavior, which can manifest as an access violation
instead of a clean error message. This is a potential contributor to
crashes like pybindgh-5993. Wrap the entire PyInit body in try/catch using
the existing PYBIND11_CATCH_INIT_EXCEPTIONS pattern.

Made-with: Cursor

* Add nullptr guards in get_internals() for better crash diagnostics

Add explicit null checks after get_pp() and create_pp_content_once()
in get_internals(), calling pybind11_fail() with descriptive messages.
These guards convert potential null-pointer dereferences (which produce
unhelpful access-violation crashes, especially on Windows) into clear
runtime_error messages that can be caught and reported as ImportError
by the try-catch added in the previous commit.

Made-with: Cursor
@rwgk rwgk removed the needs changelog Possibly needs a changelog entry label Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants