diff options
author | Raymond Hettinger <python@rcn.com> | 2004-07-02 06:41:07 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2004-07-02 06:41:07 (GMT) |
commit | 214b1c3aaea3e83302df9ea37a37b3c7548b92b1 (patch) | |
tree | 4ddeda01308aec48c7edda3188a4aad84dc9435b /Python | |
parent | 78bace7442bb89aa005950a1e37f71d4704d4cb6 (diff) | |
download | cpython-214b1c3aaea3e83302df9ea37a37b3c7548b92b1.zip cpython-214b1c3aaea3e83302df9ea37a37b3c7548b92b1.tar.gz cpython-214b1c3aaea3e83302df9ea37a37b3c7548b92b1.tar.bz2 |
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.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/bltinmodule.c | 19 | ||||
-rw-r--r-- | Python/ceval.c | 20 |
2 files changed, 29 insertions, 10 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index b3c8b09..f4f8b7a 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -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 * diff --git a/Python/ceval.c b/Python/ceval.c index ca7cea8..0c3a93d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -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) { |