Skip to content

Commit 8b45197

Browse files
committed
solved multiple access issue
1 parent 7254b3b commit 8b45197

File tree

1 file changed

+12
-20
lines changed

1 file changed

+12
-20
lines changed

include/pybind11/cast.h

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -586,25 +586,11 @@ class type_caster_generic {
586586
return inst.release();
587587
}
588588

589-
// Base methods for generic caster; there are overridden in copyable_holder_caster
589+
// Base methods for generic caster; they are overridden in copyable_holder_caster
590590
void load_value(value_and_holder &&v_h) {
591-
auto *&vptr = v_h.value_ptr();
592-
// Lazy allocation for unallocated values:
593-
if (vptr == nullptr) {
594-
auto *type = v_h.type ? v_h.type : typeinfo;
595-
if (type->operator_new) {
596-
vptr = type->operator_new(type->type_size);
597-
} else {
598-
#if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
599-
if (type->type_align > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
600-
vptr = ::operator new(type->type_size,
601-
std::align_val_t(type->type_align));
602-
else
603-
#endif
604-
vptr = ::operator new(type->type_size);
605-
}
606-
}
607-
value = vptr;
591+
value = v_h.value_ptr();
592+
if (value == nullptr)
593+
throw cast_error("Invalid object instance");
608594
}
609595
bool try_implicit_casts(handle src, bool convert) {
610596
for (auto &cast : typeinfo->implicit_casts) {
@@ -1581,7 +1567,7 @@ struct move_only_holder_caster : public type_caster_base<type> {
15811567
bool load(handle& src, bool convert) {
15821568
bool success = base::template load_impl<move_only_holder_caster<type, holder_type>>(src, convert);
15831569
if (success) // On success, remember src pointer to withdraw later
1584-
src_handle = std::addressof(src);
1570+
this->v_h = reinterpret_cast<instance *>(src.ptr())->get_value_and_holder();
15851571
return success;
15861572
}
15871573

@@ -1593,6 +1579,10 @@ struct move_only_holder_caster : public type_caster_base<type> {
15931579
explicit
15941580
#endif
15951581
operator holder_type&&() {
1582+
// In load_value() value_ptr was still valid. If it's invalid now, another argument consumed the same value before.
1583+
if (!v_h.value_ptr())
1584+
throw cast_error("Multiple access to moved argument");
1585+
v_h.value_ptr() = nullptr;
15961586
// TODO: release object instance in python
15971587
// clear_instance(src_handle->ptr()); ???
15981588

@@ -1615,6 +1605,8 @@ struct move_only_holder_caster : public type_caster_base<type> {
16151605
if (v_h.holder_constructed()) {
16161606
holder_ptr = std::addressof(v_h.template holder<holder_type>());
16171607
value = const_cast<void*>(reinterpret_cast<const void*>(holder_helper<holder_type>::get(*holder_ptr)));
1608+
if (!value)
1609+
throw cast_error("Invalid object instance");
16181610
return true;
16191611
} else {
16201612
throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) "
@@ -1636,7 +1628,7 @@ struct move_only_holder_caster : public type_caster_base<type> {
16361628

16371629

16381630
holder_type* holder_ptr = nullptr;
1639-
handle* src_handle = nullptr;
1631+
value_and_holder v_h;
16401632
};
16411633

16421634
template <typename type, typename deleter>

0 commit comments

Comments
 (0)