Skip to content

Commit eec0993

Browse files
committed
Incompatible holder types cause crash
1 parent 2fda9d5 commit eec0993

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

tests/test_smart_ptr.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,17 @@ class unique_ptr_with_addressof_operator {
8484
};
8585
PYBIND11_DECLARE_HOLDER_TYPE(T, unique_ptr_with_addressof_operator<T>);
8686

87+
// Simple custom holder that works like shared_ptr, but has a different memory layout
88+
template <typename T>
89+
class huge_shared_ptr {
90+
uint64_t padding[10];
91+
std::shared_ptr<T> impl;
92+
public:
93+
huge_shared_ptr( ) = default;
94+
huge_shared_ptr(T* p) : impl(p) { }
95+
T* get() const { return impl.get(); }
96+
};
97+
PYBIND11_DECLARE_HOLDER_TYPE(T, huge_shared_ptr<T>);
8798

8899
TEST_SUBMODULE(smart_ptr, m) {
89100

@@ -142,6 +153,10 @@ TEST_SUBMODULE(smart_ptr, m) {
142153
m.def("print_myobject2_2", [](std::shared_ptr<MyObject2> obj) { py::print(obj->toString()); });
143154
m.def("print_myobject2_3", [](const std::shared_ptr<MyObject2> &obj) { py::print(obj->toString()); });
144155
m.def("print_myobject2_4", [](const std::shared_ptr<MyObject2> *obj) { py::print((*obj)->toString()); });
156+
// Using wrong holder type should raise a cast_error at runtime
157+
m.def("make_myobject2_3", []() { return huge_shared_ptr<MyObject2>(new MyObject2(9)); });
158+
m.def("print_myobject2_5", [](const huge_shared_ptr<MyObject2> &obj) { py::print(obj.get()->toString()); });
159+
m.def("print_myobject2_6", [](const huge_shared_ptr<MyObject2> *obj) { py::print(obj->get()->toString()); });
145160

146161
// Object managed by a std::shared_ptr<>, additionally derives from std::enable_shared_from_this<>
147162
class MyObject3 : public std::enable_shared_from_this<MyObject3> {

tests/test_smart_ptr.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ def test_smart_ptr(capture):
4848
m.print_myobject2_3(o)
4949
m.print_myobject2_4(o)
5050
assert capture == "MyObject2[{i}]\n".format(i=i) * 4
51+
with pytest.raises(RuntimeError):
52+
m.print_myobject2_5(o)
53+
with pytest.raises(RuntimeError):
54+
m.print_myobject2_6(o)
55+
with pytest.raises(RuntimeError):
56+
m.make_myobject2_3()
5157

5258
cstats = ConstructorStats.get(m.MyObject2)
5359
assert cstats.alive() == 1

0 commit comments

Comments
 (0)