Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 733c893

Browse files
committed
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.
1 parent 3095a4c commit 733c893

3 files changed

Lines changed: 10 additions & 5 deletions

File tree

Python/bltinmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ builtin_eval(PyObject *self, PyObject *args)
497497
}
498498

499499
if (PyCode_Check(cmd)) {
500-
if (PyTuple_GET_SIZE(((PyCodeObject *)cmd)->co_freevars) > 0) {
500+
if (PyCode_GetNumFree((PyCodeObject *)cmd) > 0) {
501501
PyErr_SetString(PyExc_TypeError,
502502
"code object passed to eval() may not contain free variables");
503503
return NULL;

Python/ceval.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2094,7 +2094,7 @@ eval_frame(PyFrameObject *f)
20942094
int nfree;
20952095
v = POP(); /* code object */
20962096
x = PyFunction_New(v, f->f_globals);
2097-
nfree = PyTuple_GET_SIZE(((PyCodeObject *)v)->co_freevars);
2097+
nfree = PyCode_GetNumFree((PyCodeObject *)v);
20982098
Py_DECREF(v);
20992099
/* XXX Maybe this should be a separate opcode? */
21002100
if (x != NULL && nfree > 0) {
@@ -3631,6 +3631,11 @@ exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals,
36313631
if (PyDict_GetItemString(globals, "__builtins__") == NULL)
36323632
PyDict_SetItemString(globals, "__builtins__", f->f_builtins);
36333633
if (PyCode_Check(prog)) {
3634+
if (PyCode_GetNumFree((PyCodeObject *)prog) > 0) {
3635+
PyErr_SetString(PyExc_TypeError,
3636+
"code object passed to exec may not contain free variables");
3637+
return -1;
3638+
}
36343639
v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals);
36353640
}
36363641
else if (PyFile_Check(prog)) {

Python/compile.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2273,7 +2273,7 @@ com_and_test(struct compiling *c, node *n)
22732273
static int
22742274
com_make_closure(struct compiling *c, PyCodeObject *co)
22752275
{
2276-
int i, free = PyTuple_GET_SIZE(co->co_freevars);
2276+
int i, free = PyCode_GetNumFree(co);
22772277
if (free == 0)
22782278
return 0;
22792279
for (i = 0; i < free; ++i) {
@@ -2333,7 +2333,7 @@ com_test(struct compiling *c, node *n)
23332333
com_push(c, 1);
23342334
if (closure) {
23352335
com_addoparg(c, MAKE_CLOSURE, ndefs);
2336-
com_pop(c, PyTuple_GET_SIZE(co->co_freevars));
2336+
com_pop(c, PyCode_GetNumFree(co));
23372337
} else
23382338
com_addoparg(c, MAKE_FUNCTION, ndefs);
23392339
Py_DECREF(co);
@@ -3590,7 +3590,7 @@ com_classdef(struct compiling *c, node *n)
35903590
com_push(c, 1);
35913591
if (closure) {
35923592
com_addoparg(c, MAKE_CLOSURE, 0);
3593-
com_pop(c, PyTuple_GET_SIZE(co->co_freevars));
3593+
com_pop(c, PyCode_GetNumFree(co));
35943594
} else
35953595
com_addoparg(c, MAKE_FUNCTION, 0);
35963596
com_addoparg(c, CALL_FUNCTION, 0);

0 commit comments

Comments
 (0)