mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-21 20:55:11 +00:00
Check dict item accesses where it isn't already checked (#2863)
* Convert PyDict_GetXXX to internal error checking variant * Check unlikely error return from PyDict_DelItemString
This commit is contained in:
parent
5bcaaa0423
commit
6d4409466b
@ -636,7 +636,7 @@ protected:
|
||||
bool bad_arg = false;
|
||||
for (; args_copied < args_to_copy; ++args_copied) {
|
||||
const argument_record *arg_rec = args_copied < func.args.size() ? &func.args[args_copied] : nullptr;
|
||||
if (kwargs_in && arg_rec && arg_rec->name && PyDict_GetItemString(kwargs_in, arg_rec->name)) {
|
||||
if (kwargs_in && arg_rec && arg_rec->name && dict_getitemstring(kwargs_in, arg_rec->name)) {
|
||||
bad_arg = true;
|
||||
break;
|
||||
}
|
||||
@ -684,7 +684,7 @@ protected:
|
||||
|
||||
handle value;
|
||||
if (kwargs_in && arg_rec.name)
|
||||
value = PyDict_GetItemString(kwargs.ptr(), arg_rec.name);
|
||||
value = dict_getitemstring(kwargs.ptr(), arg_rec.name);
|
||||
|
||||
if (value) {
|
||||
// Consume a kwargs value
|
||||
@ -692,7 +692,9 @@ protected:
|
||||
kwargs = reinterpret_steal<dict>(PyDict_Copy(kwargs.ptr()));
|
||||
copied_kwargs = true;
|
||||
}
|
||||
PyDict_DelItemString(kwargs.ptr(), arg_rec.name);
|
||||
if (PyDict_DelItemString(kwargs.ptr(), arg_rec.name) == -1) {
|
||||
throw error_already_set();
|
||||
}
|
||||
} else if (arg_rec.value) {
|
||||
value = arg_rec.value;
|
||||
}
|
||||
@ -2139,7 +2141,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty
|
||||
if (frame && (std::string) str(frame->f_code->co_name) == name &&
|
||||
frame->f_code->co_argcount > 0) {
|
||||
PyFrame_FastToLocals(frame);
|
||||
PyObject *self_caller = PyDict_GetItem(
|
||||
PyObject *self_caller = dict_getitem(
|
||||
frame->f_locals, PyTuple_GET_ITEM(frame->f_code->co_varnames, 0));
|
||||
if (self_caller == self.ptr())
|
||||
return function();
|
||||
|
@ -485,6 +485,43 @@ inline handle get_function(handle value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// Reimplementation of python's dict helper functions to ensure that exceptions
|
||||
// aren't swallowed (see #2862)
|
||||
|
||||
// copied from cpython _PyDict_GetItemStringWithError
|
||||
inline PyObject * dict_getitemstring(PyObject *v, const char *key)
|
||||
{
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject *kv, *rv;
|
||||
kv = PyUnicode_FromString(key);
|
||||
if (kv == NULL) {
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
rv = PyDict_GetItemWithError(v, kv);
|
||||
Py_DECREF(kv);
|
||||
if (rv == NULL && PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return rv;
|
||||
#else
|
||||
return PyDict_GetItemString(v, key);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline PyObject * dict_getitem(PyObject *v, PyObject *key)
|
||||
{
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject *rv = PyDict_GetItemWithError(v, key);
|
||||
if (rv == NULL && PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return rv;
|
||||
#else
|
||||
return PyDict_GetItem(v, key);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helper aliases/functions to support implicit casting of values given to python accessors/methods.
|
||||
// When given a pyobject, this simply returns the pyobject as-is; for other C++ type, the value goes
|
||||
// through pybind11::cast(obj) to convert it to an `object`.
|
||||
|
Loading…
Reference in New Issue
Block a user