mirror of
https://github.com/python/cpython.git
synced 2025-11-01 18:51:43 +00:00
Fix 2.1 nested scopes crash reported by Evan Simpson
The new test case demonstrates the bug. Be more careful in symtable_resolve_free() to add a var to cells or frees only if it won't be added under some other rule. XXX Add new assertion that will catch this bug.
This commit is contained in:
parent
960d948e7c
commit
ddc4fd03b1
3 changed files with 32 additions and 6 deletions
|
|
@ -17,3 +17,4 @@ test_scope
|
||||||
16. check leaks
|
16. check leaks
|
||||||
17. class and global
|
17. class and global
|
||||||
18. verify that locals() works
|
18. verify that locals() works
|
||||||
|
19. var is bound and free in class
|
||||||
|
|
|
||||||
|
|
@ -436,3 +436,14 @@ verify(d.has_key('h'))
|
||||||
del d['h']
|
del d['h']
|
||||||
verify(d == {'x': 2, 'y': 7, 'w': 6})
|
verify(d == {'x': 2, 'y': 7, 'w': 6})
|
||||||
|
|
||||||
|
print "19. var is bound and free in class"
|
||||||
|
|
||||||
|
def f(x):
|
||||||
|
class C:
|
||||||
|
def m(self):
|
||||||
|
return x
|
||||||
|
a = x
|
||||||
|
return C
|
||||||
|
|
||||||
|
inst = f(3)()
|
||||||
|
verify(inst.a == inst.m())
|
||||||
|
|
|
||||||
|
|
@ -4057,7 +4057,7 @@ symtable_init_info(struct symbol_info *si)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
symtable_resolve_free(struct compiling *c, PyObject *name,
|
symtable_resolve_free(struct compiling *c, PyObject *name, int flags,
|
||||||
struct symbol_info *si)
|
struct symbol_info *si)
|
||||||
{
|
{
|
||||||
PyObject *dict, *v;
|
PyObject *dict, *v;
|
||||||
|
|
@ -4067,11 +4067,19 @@ symtable_resolve_free(struct compiling *c, PyObject *name,
|
||||||
cell var). If it occurs in a class, then the class has a
|
cell var). If it occurs in a class, then the class has a
|
||||||
method and a free variable with the same name.
|
method and a free variable with the same name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (c->c_symtable->st_cur->ste_type == TYPE_FUNCTION) {
|
if (c->c_symtable->st_cur->ste_type == TYPE_FUNCTION) {
|
||||||
|
/* If it isn't declared locally, it can't be a cell. */
|
||||||
|
if (!(flags & (DEF_LOCAL | DEF_PARAM)))
|
||||||
|
return 0;
|
||||||
v = PyInt_FromLong(si->si_ncells++);
|
v = PyInt_FromLong(si->si_ncells++);
|
||||||
dict = c->c_cellvars;
|
dict = c->c_cellvars;
|
||||||
} else {
|
} else {
|
||||||
|
/* If it is free anyway, then there is no need to do
|
||||||
|
anything here.
|
||||||
|
*/
|
||||||
|
if (is_free(flags ^ DEF_FREE_CLASS)
|
||||||
|
|| flags == DEF_FREE_CLASS)
|
||||||
|
return 0;
|
||||||
v = PyInt_FromLong(si->si_nfrees++);
|
v = PyInt_FromLong(si->si_nfrees++);
|
||||||
dict = c->c_freevars;
|
dict = c->c_freevars;
|
||||||
}
|
}
|
||||||
|
|
@ -4357,10 +4365,7 @@ symtable_load_symbols(struct compiling *c)
|
||||||
variables or declared global.
|
variables or declared global.
|
||||||
*/
|
*/
|
||||||
if (flags & (DEF_FREE | DEF_FREE_CLASS)) {
|
if (flags & (DEF_FREE | DEF_FREE_CLASS)) {
|
||||||
if ((ste->ste_type == TYPE_CLASS
|
symtable_resolve_free(c, name, flags, &si);
|
||||||
&& flags != DEF_FREE_CLASS)
|
|
||||||
|| (flags & (DEF_LOCAL | DEF_PARAM)))
|
|
||||||
symtable_resolve_free(c, name, &si);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DEF_STAR) {
|
if (flags & DEF_STAR) {
|
||||||
|
|
@ -4420,6 +4425,15 @@ symtable_load_symbols(struct compiling *c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fprintf(stderr,
|
||||||
|
"cells %d: %s\n"
|
||||||
|
"frees %d: %s\n",
|
||||||
|
si.si_ncells, PyObject_REPR(c->c_cellvars),
|
||||||
|
si.si_nfrees, PyObject_REPR(c->c_freevars));
|
||||||
|
*/
|
||||||
|
assert(PyDict_Size(c->c_freevars) == si.si_nfrees);
|
||||||
|
|
||||||
if (si.si_ncells > 1) { /* one cell is always in order */
|
if (si.si_ncells > 1) { /* one cell is always in order */
|
||||||
if (symtable_cellvar_offsets(&c->c_cellvars, c->c_argcount,
|
if (symtable_cellvar_offsets(&c->c_cellvars, c->c_argcount,
|
||||||
c->c_varnames, c->c_flags) < 0)
|
c->c_varnames, c->c_flags) < 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue