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:
Jeremy Hylton 2001-04-27 02:29:40 +00:00
parent 960d948e7c
commit ddc4fd03b1
3 changed files with 32 additions and 6 deletions

View file

@ -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

View file

@ -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())

View file

@ -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)