diff Python/compile.c @ 17637:8ff76cf30a8c legacy-trunk

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.
author Jeremy Hylton <jeremy@alum.mit.edu>
date Fri, 27 Apr 2001 02:29:40 +0000
parents 32e7d0898eab
children e3f0fd38c24b
line wrap: on
line diff
--- a/Python/compile.c	Fri Apr 27 02:25:33 2001 +0000
+++ b/Python/compile.c	Fri Apr 27 02:29:40 2001 +0000
@@ -4057,7 +4057,7 @@
 }
 
 static int
-symtable_resolve_free(struct compiling *c, PyObject *name, 
+symtable_resolve_free(struct compiling *c, PyObject *name, int flags,
 		      struct symbol_info *si)
 {
 	PyObject *dict, *v;
@@ -4067,11 +4067,19 @@
 	   cell var).  If it occurs in a class, then the class has a
 	   method and a free variable with the same name.
 	*/
-
 	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++);
 		dict = c->c_cellvars;
 	} 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++);
 		dict = c->c_freevars;
 	}
@@ -4357,10 +4365,7 @@
 		   variables or declared global.
 		*/
 		if (flags & (DEF_FREE | DEF_FREE_CLASS)) {
-		    if ((ste->ste_type == TYPE_CLASS 
-			 && flags != DEF_FREE_CLASS)
-			|| (flags & (DEF_LOCAL | DEF_PARAM)))
-			symtable_resolve_free(c, name, &si);
+			symtable_resolve_free(c, name, flags, &si);
 		}
 
 		if (flags & DEF_STAR) {
@@ -4420,6 +4425,15 @@
 		}
 	}
 
+	/*
+	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 (symtable_cellvar_offsets(&c->c_cellvars, c->c_argcount,
 					     c->c_varnames, c->c_flags) < 0)