Skip to content

Commit b96ceac

Browse files
committed
TRIGGER_SEGSEV macro, annotations for GET_STACK (vptr::get), GET_INT_STACK (pointee)
1 parent 87ca81b commit b96ceac

File tree

5 files changed

+34
-14
lines changed

5 files changed

+34
-14
lines changed

include/pybind11/cast.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,7 +1986,7 @@ class argument_loader {
19861986

19871987
template <typename Return, typename Guard, typename Func>
19881988
enable_if_t<!std::is_void<Return>::value, Return> call(Func &&f) && {
1989-
return std::move(*this).template call_impl<Return>(std::forward<Func>(f), indices{}, Guard{});
1989+
return std::move(*this).template call_impl<Return>(std::forward<Func>(f), indices{}, Guard{}); // GET_INT_STACK -3
19901990
}
19911991

19921992
template <typename Return, typename Guard, typename Func>
@@ -2014,7 +2014,7 @@ class argument_loader {
20142014

20152015
template <typename Return, typename Func, size_t... Is, typename Guard>
20162016
Return call_impl(Func &&f, index_sequence<Is...>, Guard &&) && {
2017-
return std::forward<Func>(f)(cast_op<Args>(std::move(std::get<Is>(argcasters)))...);
2017+
return std::forward<Func>(f)(cast_op<Args>(std::move(std::get<Is>(argcasters)))...); // GET_INT_STACK -2
20182018
}
20192019

20202020
std::tuple<make_caster<Args>...> argcasters;

include/pybind11/pybind11.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
# include <cxxabi.h>
5757
#endif
5858

59+
#define TRIGGER_SEGSEV { unsigned long *bad = nullptr; *bad = -1; }
60+
5961
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
6062

6163
/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
@@ -97,7 +99,7 @@ class cpp_function : public function {
9799
/// Construct a cpp_function from a class method (const, no ref-qualifier)
98100
template <typename Return, typename Class, typename... Arg, typename... Extra>
99101
cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) {
100-
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); },
102+
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); }, // GET_INT_STACK -1
101103
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
102104
}
103105

@@ -158,7 +160,7 @@ class cpp_function : public function {
158160
"The number of argument annotations does not match the number of function arguments");
159161

160162
/* Dispatch code which converts function arguments and performs the actual function call */
161-
rec->impl = [](function_call &call) -> handle {
163+
rec->impl = [](function_call &call) -> handle { // GET_INT_STACK -5
162164
cast_in args_converter;
163165

164166
/* Try to cast the function arguments into the C++ domain */
@@ -181,7 +183,7 @@ class cpp_function : public function {
181183

182184
/* Perform the function call */
183185
handle result = cast_out::cast(
184-
std::move(args_converter).template call<Return, Guard>(cap->f), policy, call.parent);
186+
std::move(args_converter).template call<Return, Guard>(cap->f), policy, call.parent); // GET_INT_STACK -4
185187

186188
/* Invoke call policy post-call hook */
187189
process_attributes<Extra...>::postcall(call, result);
@@ -502,7 +504,7 @@ class cpp_function : public function {
502504
handle parent = n_args_in > 0 ? PyTuple_GET_ITEM(args_in, 0) : nullptr,
503505
result = PYBIND11_TRY_NEXT_OVERLOAD;
504506

505-
auto self_value_and_holder = value_and_holder();
507+
auto self_value_and_holder = value_and_holder(); // cast.h
506508
if (overloads->is_constructor) {
507509
const auto tinfo = get_type_info((PyTypeObject *) overloads->scope.ptr());
508510
const auto pi = reinterpret_cast<instance *>(parent.ptr());
@@ -714,7 +716,7 @@ class cpp_function : public function {
714716
// 6. Call the function.
715717
try {
716718
loader_life_support guard{};
717-
result = func.impl(call);
719+
result = func.impl(call); // GET_INT_STACK -6
718720
} catch (reference_cast_error &) {
719721
result = PYBIND11_TRY_NEXT_OVERLOAD;
720722
}
@@ -880,7 +882,7 @@ class cpp_function : public function {
880882
} else {
881883
if (overloads->is_constructor && !self_value_and_holder.holder_constructed()) {
882884
auto *pi = reinterpret_cast<instance *>(parent.ptr());
883-
self_value_and_holder.type->init_instance(pi, nullptr);
885+
self_value_and_holder.type->init_instance(pi, nullptr); // GET_STACK -4
884886
}
885887
return result.ptr();
886888
}
@@ -1487,7 +1489,7 @@ class class_ : public detail::generic_type {
14871489
init_holder_from_existing(v_h, holder_ptr, std::is_copy_constructible<holder_type>());
14881490
v_h.set_holder_constructed();
14891491
} else if (inst->owned || detail::always_construct_holder<holder_type>::value) {
1490-
new (std::addressof(v_h.holder<holder_type>())) holder_type(v_h.value_ptr<type>());
1492+
new (std::addressof(v_h.holder<holder_type>())) holder_type(v_h.value_ptr<type>()); // GET_STACK -2
14911493
v_h.set_holder_constructed();
14921494
}
14931495
}
@@ -1502,7 +1504,7 @@ class class_ : public detail::generic_type {
15021504
register_instance(inst, v_h.value_ptr(), v_h.type);
15031505
v_h.set_instance_registered();
15041506
}
1505-
init_holder(inst, v_h, (const holder_type *) holder_ptr, v_h.value_ptr<type>());
1507+
init_holder(inst, v_h, (const holder_type *) holder_ptr, v_h.value_ptr<type>()); // GET_STACK -3
15061508
}
15071509

15081510
/// Deallocates an instance; via holder, if constructed; otherwise via operator delete.

include/pybind11/vptr_holder.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <pybind11/pybind11.h>
44

5+
#include <iostream>
56
#include <memory>
67
#include <variant>
78

@@ -11,9 +12,12 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
1112
// To enable passing of unique_ptr as in pure C++.
1213
template <typename T> class vptr {
1314
public:
14-
explicit vptr(T *ptr = nullptr) : vptr_{std::unique_ptr<T>(ptr)} {}
15-
explicit vptr(std::unique_ptr<T> u) : vptr_{std::move(u)} {}
16-
explicit vptr(std::shared_ptr<T> s) : vptr_{s} {}
15+
explicit vptr(T *ptr = nullptr) : vptr_{std::unique_ptr<T>(ptr)} {
16+
std::cout << std::endl << "explicit vptr(T *ptr = nullptr)" << std::endl;
17+
//TRIGGER_SEGSEV
18+
}
19+
explicit vptr(std::unique_ptr<T> u) : vptr_{std::move(u)} { std::cout << std::endl << "explicit vptr(std::unique_ptr<T> u)" << std::endl; }
20+
explicit vptr(std::shared_ptr<T> s) : vptr_{s} { std::cout << std::endl << "explicit vptr(std::shared_ptr<T> s)" << std::endl; }
1721

1822
int ownership_type() const {
1923
if (std::get_if<0>(&vptr_)) {
@@ -26,6 +30,7 @@ template <typename T> class vptr {
2630
}
2731

2832
T *get() {
33+
std::cout << std::endl << "vptr::get" << std::endl;
2934
auto u = std::get_if<0>(&vptr_);
3035
if (u) {
3136
return u->get();
@@ -64,7 +69,7 @@ template <typename T> class vptr {
6469
};
6570

6671
template <typename T> class vptr_holder : public vptr<T> {
67-
using vptr<T>::vptr;
72+
using vptr<T>::vptr; // GET_STACK -1
6873
};
6974

7075
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

tests/test_unique_ptr_member.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class pointee { // NOT copyable.
1616

1717
int get_int() const {
1818
to_cout("pointee::get_int()");
19+
//TRIGGER_SEGSEV
1920
return 213;
2021
}
2122

tests/work.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from pybind11_tests import unique_ptr_member as m
2+
3+
4+
def test_pointee_and_ptr_owner():
5+
m.to_cout("")
6+
obj = m.pointee()
7+
assert obj.get_int() == 213
8+
del obj
9+
print("DONE.", flush=True)
10+
11+
12+
test_pointee_and_ptr_owner()

0 commit comments

Comments
 (0)