mirror of
https://github.com/python/cpython.git
synced 2025-10-27 16:57:08 +00:00
SF Bug #215126: Over restricted type checking on eval() function
The builtin eval() function now accepts any mapping for the locals argument. Time sensitive steps guarded by PyDict_CheckExact() to keep from slowing down the normal case. My timings so no measurable impact.
This commit is contained in:
parent
78bace7442
commit
214b1c3aae
9 changed files with 103 additions and 31 deletions
|
|
@ -455,11 +455,17 @@ builtin_eval(PyObject *self, PyObject *args)
|
|||
char *str;
|
||||
PyCompilerFlags cf;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O|O!O!:eval",
|
||||
&cmd,
|
||||
&PyDict_Type, &globals,
|
||||
&PyDict_Type, &locals))
|
||||
if (!PyArg_UnpackTuple(args, "eval", 1, 3, &cmd, &globals, &locals))
|
||||
return NULL;
|
||||
if (locals != Py_None && !PyMapping_Check(locals)) {
|
||||
PyErr_SetString(PyExc_TypeError, "locals must be a mapping");
|
||||
return NULL;
|
||||
}
|
||||
if (globals != Py_None && !PyDict_Check(globals)) {
|
||||
PyErr_SetString(PyExc_TypeError, PyMapping_Check(globals) ?
|
||||
"globals must be a real dict; try eval(expr, {}, mapping)"
|
||||
: "globals must be a dict");
|
||||
}
|
||||
if (globals == Py_None) {
|
||||
globals = PyEval_GetGlobals();
|
||||
if (locals == Py_None)
|
||||
|
|
@ -517,8 +523,9 @@ PyDoc_STRVAR(eval_doc,
|
|||
Evaluate the source in the context of globals and locals.\n\
|
||||
The source may be a string representing a Python expression\n\
|
||||
or a code object as returned by compile().\n\
|
||||
The globals and locals are dictionaries, defaulting to the current\n\
|
||||
globals and locals. If only globals is given, locals defaults to it.");
|
||||
The globals must be a dictionary and locals can be any mappping,\n\
|
||||
defaulting to the current globals and locals.\n\
|
||||
If only globals is given, locals defaults to it.\n");
|
||||
|
||||
|
||||
static PyObject *
|
||||
|
|
|
|||
|
|
@ -1643,7 +1643,10 @@ PyEval_EvalFrame(PyFrameObject *f)
|
|||
w = GETITEM(names, oparg);
|
||||
v = POP();
|
||||
if ((x = f->f_locals) != NULL) {
|
||||
err = PyDict_SetItem(x, w, v);
|
||||
if (PyDict_CheckExact(v))
|
||||
err = PyDict_SetItem(x, w, v);
|
||||
else
|
||||
err = PyObject_SetItem(x, w, v);
|
||||
Py_DECREF(v);
|
||||
if (err == 0) continue;
|
||||
break;
|
||||
|
|
@ -1656,7 +1659,7 @@ PyEval_EvalFrame(PyFrameObject *f)
|
|||
case DELETE_NAME:
|
||||
w = GETITEM(names, oparg);
|
||||
if ((x = f->f_locals) != NULL) {
|
||||
if ((err = PyDict_DelItem(x, w)) != 0)
|
||||
if ((err = PyObject_DelItem(x, w)) != 0)
|
||||
format_exc_check_arg(PyExc_NameError,
|
||||
NAME_ERROR_MSG ,w);
|
||||
break;
|
||||
|
|
@ -1733,13 +1736,22 @@ PyEval_EvalFrame(PyFrameObject *f)
|
|||
|
||||
case LOAD_NAME:
|
||||
w = GETITEM(names, oparg);
|
||||
if ((x = f->f_locals) == NULL) {
|
||||
if ((v = f->f_locals) == NULL) {
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"no locals when loading %s",
|
||||
PyObject_REPR(w));
|
||||
break;
|
||||
}
|
||||
x = PyDict_GetItem(x, w);
|
||||
if (PyDict_CheckExact(v))
|
||||
x = PyDict_GetItem(v, w);
|
||||
else {
|
||||
x = PyObject_GetItem(v, w);
|
||||
if (x == NULL && PyErr_Occurred()) {
|
||||
if (!PyErr_ExceptionMatches(PyExc_KeyError))
|
||||
break;
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
if (x == NULL) {
|
||||
x = PyDict_GetItem(f->f_globals, w);
|
||||
if (x == NULL) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue