fix: throwing repr caused a segfault (#2389)

* fix: throwing repr caused a segfault

* fixup! ci: include Python 3.9 RC1 (#2387)
This commit is contained in:
Henry Schreiner 2020-08-18 07:14:34 -04:00 committed by GitHub
parent 7dd2bdb0b3
commit cf0a64596e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 2 deletions

View File

@ -776,7 +776,11 @@ protected:
for (size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti) { for (size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti) {
if (!some_args) some_args = true; if (!some_args) some_args = true;
else msg += ", "; else msg += ", ";
try {
msg += pybind11::repr(args_[ti]); msg += pybind11::repr(args_[ti]);
} catch (const error_already_set&) {
msg += "<repr raised Error>";
}
} }
if (kwargs_in) { if (kwargs_in) {
auto kwargs = reinterpret_borrow<dict>(kwargs_in); auto kwargs = reinterpret_borrow<dict>(kwargs_in);
@ -787,7 +791,12 @@ protected:
for (auto kwarg : kwargs) { for (auto kwarg : kwargs) {
if (first) first = false; if (first) first = false;
else msg += ", "; else msg += ", ";
msg += pybind11::str("{}={!r}").format(kwarg.first, kwarg.second); msg += pybind11::str("{}=").format(kwarg.first);
try {
msg += pybind11::repr(kwarg.second);
} catch (const error_already_set&) {
msg += "<repr raised Error>";
}
} }
} }
} }

View File

@ -218,4 +218,7 @@ TEST_SUBMODULE(exceptions, m) {
} }
}); });
// Test repr that cannot be displayed
m.def("simple_bool_passthrough", [](bool x) {return x;});
} }

View File

@ -178,3 +178,14 @@ def test_nested_throws(capture):
with pytest.raises(m.MyException5) as excinfo: with pytest.raises(m.MyException5) as excinfo:
m.try_catch(m.MyException, pycatch, m.MyException, m.throws5) m.try_catch(m.MyException, pycatch, m.MyException, m.throws5)
assert str(excinfo.value) == "this is a helper-defined translated exception" assert str(excinfo.value) == "this is a helper-defined translated exception"
# This can often happen if you wrap a pybind11 class in a Python wrapper
def test_invalid_repr():
class MyRepr(object):
def __repr__(self):
raise AttributeError("Example error")
with pytest.raises(TypeError):
m.simple_bool_passthrough(MyRepr())