-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Fix dangling pointer in internals::registered_types_cpp_fast from #5842 #5867
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ind#5842 @oremanj pointed out in a comment on pybind#5842 that I missed part of the nanobind PR I was porting in such a way that we could have dangling pointers in internals::registered_types_cpp_fast. This PR adds a test that reproed the bug and then fixes the test.
include/pybind11/detail/internals.h
Outdated
// keys (the type_info from each DSO) mapped to the same | ||
// type_info*. We need to keep track of these aliases so that we clean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// keys (the type_info from each DSO) mapped to the same | |
// type_info*. We need to keep track of these aliases so that we clean | |
// keys (the std::type_info from each DSO) mapped to the same | |
// detail::type_info*. We need to keep track of these aliases so that we clean |
Suggest disambiguating since both the key and value types are something::type_info
include/pybind11/detail/internals.h
Outdated
// nb_alias_chain` added in | ||
// https://github.com/wjakob/nanobind/commit/b515b1f7f2f4ecc0357818e6201c94a9f4cbfdc2 | ||
#if PYBIND11_INTERNALS_VERSION >= 12 | ||
struct alias_chain_entry { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use std::forward_list
instead of rolling your own singly linked list. nanobind goes to a lot of trouble to avoid anything from the STL, while pybind11 already has other uses of forward_list and it is basically the same thing you wrote here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL sizeof(std::forward_list) == 8 and it's in C++11, SGTM
def test_cross_module_use_after_one_module_dealloc(): | ||
# This is a regression test for a bug that occurred during development of | ||
# internals::registered_types_cpp_fast (see #5842). registered_types_cpp_fast maps | ||
# &typeid(T) to a raw non-owning pointer to a Python metaclass. If two DSOs both |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are just Python classes (types), not metaclasses (their instances are not types). I might say "type object pointer" to disambiguate from the std::type_info pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You will need to skip the new test on 3.13 free-threaded, since types are immortal there. It should work fine on 3.14+ free-threaded. Suggestions are what I expect you need to make clang-tidy happy.
struct UnrelatedClass {}; | ||
|
||
TEST_SUBMODULE(class_cross_module_use_after_one_module_dealloc, m) { | ||
m.def("register_and_instantiate_cross_dso_class", [](py::module_ m) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m.def("register_and_instantiate_cross_dso_class", [](py::module_ m) { | |
m.def("register_and_instantiate_cross_dso_class", [](const py::module_ &m) { |
return CrossDSOClass(); | ||
}); | ||
m.def("register_unrelated_class", | ||
[](py::module_ m) { py::class_<UnrelatedClass>(m, "UnrelatedClass"); }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[](py::module_ m) { py::class_<UnrelatedClass>(m, "UnrelatedClass"); }); | |
[](const py::module_ &m) { py::class_<UnrelatedClass>(m, "UnrelatedClass"); }); |
m.def("missing_header_return", []() { return std::vector<float>(); }); | ||
|
||
// test_class_cross_module_use_after_one_module_dealloc | ||
m.def("consume_cross_dso_class", [](CrossDSOClass) {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m.def("consume_cross_dso_class", [](CrossDSOClass) {}); | |
m.def("consume_cross_dso_class", [](const CrossDSOClass &) {}); |
Thanks for fixing things up @oremanj! Was out today, planned to get to it tomorrow |
Description
@oremanj pointed out in a comment on #5842 that I missed part of the nanobind PR I was porting in such a way that we could have dangling pointers in internals::registered_types_cpp_fast. This PR adds a test that reproed the bug and then fixes the test.