mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05: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;
|
bool bad_arg = false;
|
||||||
for (; args_copied < args_to_copy; ++args_copied) {
|
for (; args_copied < args_to_copy; ++args_copied) {
|
||||||
const argument_record *arg_rec = args_copied < func.args.size() ? &func.args[args_copied] : nullptr;
|
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;
|
bad_arg = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -684,7 +684,7 @@ protected:
|
|||||||
|
|
||||||
handle value;
|
handle value;
|
||||||
if (kwargs_in && arg_rec.name)
|
if (kwargs_in && arg_rec.name)
|
||||||
value = PyDict_GetItemString(kwargs.ptr(), arg_rec.name);
|
value = dict_getitemstring(kwargs.ptr(), arg_rec.name);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
// Consume a kwargs value
|
// Consume a kwargs value
|
||||||
@ -692,7 +692,9 @@ protected:
|
|||||||
kwargs = reinterpret_steal<dict>(PyDict_Copy(kwargs.ptr()));
|
kwargs = reinterpret_steal<dict>(PyDict_Copy(kwargs.ptr()));
|
||||||
copied_kwargs = true;
|
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) {
|
} else if (arg_rec.value) {
|
||||||
value = 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 &&
|
if (frame && (std::string) str(frame->f_code->co_name) == name &&
|
||||||
frame->f_code->co_argcount > 0) {
|
frame->f_code->co_argcount > 0) {
|
||||||
PyFrame_FastToLocals(frame);
|
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));
|
frame->f_locals, PyTuple_GET_ITEM(frame->f_code->co_varnames, 0));
|
||||||
if (self_caller == self.ptr())
|
if (self_caller == self.ptr())
|
||||||
return function();
|
return function();
|
||||||
|
@ -485,6 +485,43 @@ inline handle get_function(handle value) {
|
|||||||
return 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.
|
// 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
|
// 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`.
|
// through pybind11::cast(obj) to convert it to an `object`.
|
||||||
|
Loading…
Reference in New Issue
Block a user