Fix invalid access when reinterpret_casting a non-pybind11 PyObject* to instance* (found by Valgrind in #2746) (#2755)

This commit is contained in:
Yannick Jadoul 2020-12-31 17:10:11 +01:00 committed by GitHub
parent 2110d2d8ba
commit e612043d43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -504,15 +504,15 @@ protected:
auto self_value_and_holder = value_and_holder(); auto self_value_and_holder = value_and_holder();
if (overloads->is_constructor) { if (overloads->is_constructor) {
const auto tinfo = get_type_info((PyTypeObject *) overloads->scope.ptr()); if (!PyObject_TypeCheck(parent.ptr(), (PyTypeObject *) overloads->scope.ptr())) {
const auto pi = reinterpret_cast<instance *>(parent.ptr());
self_value_and_holder = pi->get_value_and_holder(tinfo, false);
if (!self_value_and_holder.type || !self_value_and_holder.inst) {
PyErr_SetString(PyExc_TypeError, "__init__(self, ...) called with invalid `self` argument"); PyErr_SetString(PyExc_TypeError, "__init__(self, ...) called with invalid `self` argument");
return nullptr; return nullptr;
} }
const auto tinfo = get_type_info((PyTypeObject *) overloads->scope.ptr());
const auto pi = reinterpret_cast<instance *>(parent.ptr());
self_value_and_holder = pi->get_value_and_holder(tinfo, true);
// If this value is already registered it must mean __init__ is invoked multiple times; // If this value is already registered it must mean __init__ is invoked multiple times;
// we really can't support that in C++, so just ignore the second __init__. // we really can't support that in C++, so just ignore the second __init__.
if (self_value_and_holder.instance_registered()) if (self_value_and_holder.instance_registered())