diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-02-23 17:55:27 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-02-23 17:55:27 (GMT) |
commit | 74b3bc47df9979e54c1f0c7866730eb499705f0e (patch) | |
tree | 81c0697e22f1b41bb628669a016d3ad9dd49b203 | |
parent | 3e13b1e48bdd0550929f55bac11571116cd655ab (diff) | |
download | cpython-74b3bc47df9979e54c1f0c7866730eb499705f0e.zip cpython-74b3bc47df9979e54c1f0c7866730eb499705f0e.tar.gz cpython-74b3bc47df9979e54c1f0c7866730eb499705f0e.tar.bz2 |
Fix for bug 133489: compiler leaks memory
Two different but related problems:
1. PySymtable_Free() must explicitly DECREF(st->st_cur), which should
always point to the global symtable entry. This entry is setup by the
first enter_scope() call, but there is never a corresponding
exit_scope() call.
Since each entry has a reference to scopes defined within it, the
missing DECREF caused all symtable entries to be leaked.
2. The leak here masked a separate problem with
PySymtableEntry_New(). When the requested entry was found in
st->st_symbols, the entry was returned without doing an INCREF.
And problem c) The ste_children slot was getting two copies of each
child entry, because it was populating the slot on the first and
second passes. Now only populate on the first pass.
-rw-r--r-- | Python/compile.c | 8 | ||||
-rw-r--r-- | Python/symtable.c | 8 |
2 files changed, 11 insertions, 5 deletions
diff --git a/Python/compile.c b/Python/compile.c index f2d424b..7eac91a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3912,8 +3912,10 @@ jcompile(node *n, char *filename, struct compiling *base) PyErr_SetString(PyExc_SystemError, "lost syntax error"); } exit: - if (base == NULL) + if (base == NULL) { PySymtable_Free(sc.c_symtable); + sc.c_symtable = NULL; + } com_free(&sc); return co; } @@ -4193,6 +4195,7 @@ PySymtable_Free(struct symtable *st) { Py_XDECREF(st->st_symbols); Py_XDECREF(st->st_stack); + Py_XDECREF(st->st_cur); PyMem_Free((void *)st); } @@ -4359,10 +4362,11 @@ symtable_enter_scope(struct symtable *st, char *name, int type, PySymtableEntry_New(st, name, type, lineno); if (strcmp(name, TOP) == 0) st->st_global = st->st_cur->ste_symbols; - if (prev) + if (prev && st->st_pass == 1) { if (PyList_Append(prev->ste_children, (PyObject *)st->st_cur) < 0) st->st_errors++; + } } static int diff --git a/Python/symtable.c b/Python/symtable.c index 5dc0272..0d2e324 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -13,8 +13,10 @@ PySymtableEntry_New(struct symtable *st, char *name, int type, int lineno) if (k == NULL) goto fail; v = PyDict_GetItem(st->st_symbols, k); - if (v) /* XXX could check that name, type, lineno match */ - return v; + if (v) /* XXX could check that name, type, lineno match */ { + Py_INCREF(v); + return v; + } ste = (PySymtableEntryObject *)PyObject_New(PySymtableEntryObject, &PySymtableEntry_Type); @@ -69,7 +71,7 @@ PySymtableEntry_New(struct symtable *st, char *name, int type, int lineno) if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0) goto fail; - + return (PyObject *)ste; fail: Py_XDECREF(ste); |