Skip to content

Commit cf0a645

Browse files
authored
fix: throwing repr caused a segfault (#2389)
* fix: throwing repr caused a segfault * fixup! ci: include Python 3.9 RC1 (#2387)
1 parent 7dd2bdb commit cf0a645

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

include/pybind11/pybind11.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,11 @@ class cpp_function : public function {
776776
for (size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti) {
777777
if (!some_args) some_args = true;
778778
else msg += ", ";
779-
msg += pybind11::repr(args_[ti]);
779+
try {
780+
msg += pybind11::repr(args_[ti]);
781+
} catch (const error_already_set&) {
782+
msg += "<repr raised Error>";
783+
}
780784
}
781785
if (kwargs_in) {
782786
auto kwargs = reinterpret_borrow<dict>(kwargs_in);
@@ -787,7 +791,12 @@ class cpp_function : public function {
787791
for (auto kwarg : kwargs) {
788792
if (first) first = false;
789793
else msg += ", ";
790-
msg += pybind11::str("{}={!r}").format(kwarg.first, kwarg.second);
794+
msg += pybind11::str("{}=").format(kwarg.first);
795+
try {
796+
msg += pybind11::repr(kwarg.second);
797+
} catch (const error_already_set&) {
798+
msg += "<repr raised Error>";
799+
}
791800
}
792801
}
793802
}

tests/test_exceptions.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,7 @@ TEST_SUBMODULE(exceptions, m) {
218218
}
219219
});
220220

221+
// Test repr that cannot be displayed
222+
m.def("simple_bool_passthrough", [](bool x) {return x;});
223+
221224
}

tests/test_exceptions.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,14 @@ def pycatch(exctype, f, *args):
178178
with pytest.raises(m.MyException5) as excinfo:
179179
m.try_catch(m.MyException, pycatch, m.MyException, m.throws5)
180180
assert str(excinfo.value) == "this is a helper-defined translated exception"
181+
182+
183+
# This can often happen if you wrap a pybind11 class in a Python wrapper
184+
def test_invalid_repr():
185+
186+
class MyRepr(object):
187+
def __repr__(self):
188+
raise AttributeError("Example error")
189+
190+
with pytest.raises(TypeError):
191+
m.simple_bool_passthrough(MyRepr())

0 commit comments

Comments
 (0)