Commit 4d3307aa authored by Jeremy Hylton's avatar Jeremy Hylton

Fix for SF bug [ #492403 ] exec() segfaults on closure's func_code

Based on the patch from Danny Yoo.  The fix is in exec_statement() in
ceval.c.

There are also changes to introduce use of PyCode_GetNumFree() in
several places.
parent e953402d
...@@ -497,7 +497,7 @@ builtin_eval(PyObject *self, PyObject *args) ...@@ -497,7 +497,7 @@ builtin_eval(PyObject *self, PyObject *args)
} }
if (PyCode_Check(cmd)) { if (PyCode_Check(cmd)) {
if (PyTuple_GET_SIZE(((PyCodeObject *)cmd)->co_freevars) > 0) { if (PyCode_GetNumFree((PyCodeObject *)cmd) > 0) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"code object passed to eval() may not contain free variables"); "code object passed to eval() may not contain free variables");
return NULL; return NULL;
......
...@@ -2094,7 +2094,7 @@ eval_frame(PyFrameObject *f) ...@@ -2094,7 +2094,7 @@ eval_frame(PyFrameObject *f)
int nfree; int nfree;
v = POP(); /* code object */ v = POP(); /* code object */
x = PyFunction_New(v, f->f_globals); x = PyFunction_New(v, f->f_globals);
nfree = PyTuple_GET_SIZE(((PyCodeObject *)v)->co_freevars); nfree = PyCode_GetNumFree((PyCodeObject *)v);
Py_DECREF(v); Py_DECREF(v);
/* XXX Maybe this should be a separate opcode? */ /* XXX Maybe this should be a separate opcode? */
if (x != NULL && nfree > 0) { if (x != NULL && nfree > 0) {
...@@ -3631,6 +3631,11 @@ exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals, ...@@ -3631,6 +3631,11 @@ exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals,
if (PyDict_GetItemString(globals, "__builtins__") == NULL) if (PyDict_GetItemString(globals, "__builtins__") == NULL)
PyDict_SetItemString(globals, "__builtins__", f->f_builtins); PyDict_SetItemString(globals, "__builtins__", f->f_builtins);
if (PyCode_Check(prog)) { if (PyCode_Check(prog)) {
if (PyCode_GetNumFree((PyCodeObject *)prog) > 0) {
PyErr_SetString(PyExc_TypeError,
"code object passed to exec may not contain free variables");
return -1;
}
v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals); v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals);
} }
else if (PyFile_Check(prog)) { else if (PyFile_Check(prog)) {
......
...@@ -2273,7 +2273,7 @@ com_and_test(struct compiling *c, node *n) ...@@ -2273,7 +2273,7 @@ com_and_test(struct compiling *c, node *n)
static int static int
com_make_closure(struct compiling *c, PyCodeObject *co) com_make_closure(struct compiling *c, PyCodeObject *co)
{ {
int i, free = PyTuple_GET_SIZE(co->co_freevars); int i, free = PyCode_GetNumFree(co);
if (free == 0) if (free == 0)
return 0; return 0;
for (i = 0; i < free; ++i) { for (i = 0; i < free; ++i) {
...@@ -2333,7 +2333,7 @@ com_test(struct compiling *c, node *n) ...@@ -2333,7 +2333,7 @@ com_test(struct compiling *c, node *n)
com_push(c, 1); com_push(c, 1);
if (closure) { if (closure) {
com_addoparg(c, MAKE_CLOSURE, ndefs); com_addoparg(c, MAKE_CLOSURE, ndefs);
com_pop(c, PyTuple_GET_SIZE(co->co_freevars)); com_pop(c, PyCode_GetNumFree(co));
} else } else
com_addoparg(c, MAKE_FUNCTION, ndefs); com_addoparg(c, MAKE_FUNCTION, ndefs);
Py_DECREF(co); Py_DECREF(co);
...@@ -3590,7 +3590,7 @@ com_classdef(struct compiling *c, node *n) ...@@ -3590,7 +3590,7 @@ com_classdef(struct compiling *c, node *n)
com_push(c, 1); com_push(c, 1);
if (closure) { if (closure) {
com_addoparg(c, MAKE_CLOSURE, 0); com_addoparg(c, MAKE_CLOSURE, 0);
com_pop(c, PyTuple_GET_SIZE(co->co_freevars)); com_pop(c, PyCode_GetNumFree(co));
} else } else
com_addoparg(c, MAKE_FUNCTION, 0); com_addoparg(c, MAKE_FUNCTION, 0);
com_addoparg(c, CALL_FUNCTION, 0); com_addoparg(c, CALL_FUNCTION, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment