Skip to content

Commit 53be819

Browse files
committed
Don't attempt to constructor an impossible shared_ptr
Fixes #1178 It's possible for a non-destructible base class to be declared; such a holder *can* be obtained via `std::enable_shared_from_this`, but a shared_ptr cannot be constructed from a returned pointer. This commit puts the holder constructor behind a `std::is_destructible` check, giving a runtime failure if we are ever given such a pointer without a valid `shared_from_this()` shared pointer.
1 parent 0a0758c commit 53be819

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

include/pybind11/pybind11.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,24 @@ class class_ : public detail::generic_type {
12621262
}
12631263

12641264
private:
1265+
template <typename T = type, detail::enable_if_t<std::is_destructible<T>::value, int> = 0>
1266+
static void init_shared_holder_from_pointer(detail::value_and_holder &v_h) {
1267+
new (&v_h.holder<holder_type>()) holder_type(v_h.value_ptr<type>());
1268+
v_h.set_holder_constructed();
1269+
}
1270+
1271+
template <typename T = type, detail::enable_if_t<!std::is_destructible<T>::value, int> = 0>
1272+
static void init_shared_holder_from_pointer(detail::value_and_holder &) {
1273+
pybind11_fail("Unable to construct C++ holder"
1274+
#if defined(NDEBUG)
1275+
" (compile in debug mode for type details)"
1276+
#else
1277+
": cannot construct a `" + type_id<holder_type>() + "' holder around a non-destructible `" +
1278+
type_id<type>() + "' pointer"
1279+
#endif
1280+
);
1281+
}
1282+
12651283
/// Initialize holder object, variant 1: object derives from enable_shared_from_this
12661284
template <typename T>
12671285
static void init_holder(detail::instance *inst, detail::value_and_holder &v_h,
@@ -1276,8 +1294,7 @@ class class_ : public detail::generic_type {
12761294
} catch (const std::bad_weak_ptr &) {}
12771295

12781296
if (!v_h.holder_constructed() && inst->owned) {
1279-
new (&v_h.holder<holder_type>()) holder_type(v_h.value_ptr<type>());
1280-
v_h.set_holder_constructed();
1297+
init_shared_holder_from_pointer(v_h);
12811298
}
12821299
}
12831300

0 commit comments

Comments
 (0)