mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Fix a lot of memory and ref leaks in error paths.
(Call symtable_exit_block or compiler_exit_scope as appropriate) Use PyMem_Free on c_future since it was allocated with PyMem_Malloc
This commit is contained in:
parent
6576bd844f
commit
b6fc9df8fc
2 changed files with 112 additions and 44 deletions
|
@ -302,7 +302,7 @@ compiler_free(struct compiler *c)
|
||||||
if (c->c_st)
|
if (c->c_st)
|
||||||
PySymtable_Free(c->c_st);
|
PySymtable_Free(c->c_st);
|
||||||
if (c->c_future)
|
if (c->c_future)
|
||||||
PyObject_Free((void *)c->c_future);
|
PyMem_Free(c->c_future);
|
||||||
Py_DECREF(c->c_stack);
|
Py_DECREF(c->c_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1607,6 +1607,13 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
|
||||||
return 0; \
|
return 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ADDOP_IN_SCOPE(C, OP) { \
|
||||||
|
if (!compiler_addop((C), (OP))) { \
|
||||||
|
compiler_exit_scope(c); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define ADDOP_O(C, OP, O, TYPE) { \
|
#define ADDOP_O(C, OP, O, TYPE) { \
|
||||||
if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) \
|
if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) \
|
||||||
return 0; \
|
return 0; \
|
||||||
|
@ -1641,6 +1648,13 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
|
||||||
return 0; \
|
return 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VISIT_IN_SCOPE(C, TYPE, V) {\
|
||||||
|
if (!compiler_visit_ ## TYPE((C), (V))) { \
|
||||||
|
compiler_exit_scope(c); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define VISIT_SLICE(C, V, CTX) {\
|
#define VISIT_SLICE(C, V, CTX) {\
|
||||||
if (!compiler_visit_slice((C), (V), (CTX))) \
|
if (!compiler_visit_slice((C), (V), (CTX))) \
|
||||||
return 0; \
|
return 0; \
|
||||||
|
@ -1656,6 +1670,18 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VISIT_SEQ_IN_SCOPE(C, TYPE, SEQ) { \
|
||||||
|
int i; \
|
||||||
|
asdl_seq *seq = (SEQ); /* avoid variable capture */ \
|
||||||
|
for (i = 0; i < asdl_seq_LEN(seq); i++) { \
|
||||||
|
TYPE ## _ty elt = asdl_seq_GET(seq, i); \
|
||||||
|
if (!compiler_visit_ ## TYPE((C), elt)) { \
|
||||||
|
compiler_exit_scope(c); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compiler_isdocstring(stmt_ty s)
|
compiler_isdocstring(stmt_ty s)
|
||||||
{
|
{
|
||||||
|
@ -1708,15 +1734,15 @@ compiler_mod(struct compiler *c, mod_ty mod)
|
||||||
break;
|
break;
|
||||||
case Interactive_kind:
|
case Interactive_kind:
|
||||||
c->c_interactive = 1;
|
c->c_interactive = 1;
|
||||||
VISIT_SEQ(c, stmt, mod->v.Interactive.body);
|
VISIT_SEQ_IN_SCOPE(c, stmt, mod->v.Interactive.body);
|
||||||
break;
|
break;
|
||||||
case Expression_kind:
|
case Expression_kind:
|
||||||
VISIT(c, expr, mod->v.Expression.body);
|
VISIT_IN_SCOPE(c, expr, mod->v.Expression.body);
|
||||||
addNone = 0;
|
addNone = 0;
|
||||||
break;
|
break;
|
||||||
case Suite_kind:
|
case Suite_kind:
|
||||||
assert(0); /* XXX: what should we do here? */
|
assert(0); /* XXX: what should we do here? */
|
||||||
VISIT_SEQ(c, stmt, mod->v.Suite.body);
|
VISIT_SEQ_IN_SCOPE(c, stmt, mod->v.Suite.body);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -1890,7 +1916,7 @@ compiler_function(struct compiler *c, stmt_ty s)
|
||||||
if (i == 0 && s2->kind == Expr_kind &&
|
if (i == 0 && s2->kind == Expr_kind &&
|
||||||
s2->v.Expr.value->kind == Str_kind)
|
s2->v.Expr.value->kind == Str_kind)
|
||||||
continue;
|
continue;
|
||||||
VISIT(c, stmt, s2);
|
VISIT_IN_SCOPE(c, stmt, s2);
|
||||||
}
|
}
|
||||||
co = assemble(c, 1);
|
co = assemble(c, 1);
|
||||||
compiler_exit_scope(c);
|
compiler_exit_scope(c);
|
||||||
|
@ -1945,8 +1971,8 @@ compiler_class(struct compiler *c, stmt_ty s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ADDOP(c, LOAD_LOCALS);
|
ADDOP_IN_SCOPE(c, LOAD_LOCALS);
|
||||||
ADDOP(c, RETURN_VALUE);
|
ADDOP_IN_SCOPE(c, RETURN_VALUE);
|
||||||
co = assemble(c, 1);
|
co = assemble(c, 1);
|
||||||
compiler_exit_scope(c);
|
compiler_exit_scope(c);
|
||||||
if (co == NULL)
|
if (co == NULL)
|
||||||
|
@ -1981,8 +2007,8 @@ compiler_lambda(struct compiler *c, expr_ty e)
|
||||||
compiler_arguments(c, args);
|
compiler_arguments(c, args);
|
||||||
|
|
||||||
c->u->u_argcount = asdl_seq_LEN(args->args);
|
c->u->u_argcount = asdl_seq_LEN(args->args);
|
||||||
VISIT(c, expr, e->v.Lambda.body);
|
VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);
|
||||||
ADDOP(c, RETURN_VALUE);
|
ADDOP_IN_SCOPE(c, RETURN_VALUE);
|
||||||
co = assemble(c, 1);
|
co = assemble(c, 1);
|
||||||
compiler_exit_scope(c);
|
compiler_exit_scope(c);
|
||||||
if (co == NULL)
|
if (co == NULL)
|
||||||
|
|
|
@ -16,7 +16,7 @@ PySTEntry_New(struct symtable *st, identifier name, _Py_block_ty block,
|
||||||
void *key, int lineno)
|
void *key, int lineno)
|
||||||
{
|
{
|
||||||
PySTEntryObject *ste = NULL;
|
PySTEntryObject *ste = NULL;
|
||||||
PyObject *k, *v;
|
PyObject *k;
|
||||||
|
|
||||||
k = PyLong_FromVoidPtr(key);
|
k = PyLong_FromVoidPtr(key);
|
||||||
if (k == NULL)
|
if (k == NULL)
|
||||||
|
@ -30,20 +30,21 @@ PySTEntry_New(struct symtable *st, identifier name, _Py_block_ty block,
|
||||||
ste->ste_name = name;
|
ste->ste_name = name;
|
||||||
Py_INCREF(name);
|
Py_INCREF(name);
|
||||||
|
|
||||||
v = PyDict_New();
|
ste->ste_symbols = NULL;
|
||||||
if (v == NULL)
|
ste->ste_varnames = NULL;
|
||||||
goto fail;
|
ste->ste_children = NULL;
|
||||||
ste->ste_symbols = v;
|
|
||||||
|
|
||||||
v = PyList_New(0);
|
ste->ste_symbols = PyDict_New();
|
||||||
if (v == NULL)
|
if (ste->ste_symbols == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
ste->ste_varnames = v;
|
|
||||||
|
|
||||||
v = PyList_New(0);
|
ste->ste_varnames = PyList_New(0);
|
||||||
if (v == NULL)
|
if (ste->ste_varnames == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ste->ste_children = PyList_New(0);
|
||||||
|
if (ste->ste_children == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
ste->ste_children = v;
|
|
||||||
|
|
||||||
ste->ste_type = block;
|
ste->ste_type = block;
|
||||||
ste->ste_unoptimized = 0;
|
ste->ste_unoptimized = 0;
|
||||||
|
@ -187,6 +188,8 @@ symtable_new(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
st->st_filename = NULL;
|
st->st_filename = NULL;
|
||||||
|
st->st_symbols = NULL;
|
||||||
|
|
||||||
if ((st->st_stack = PyList_New(0)) == NULL)
|
if ((st->st_stack = PyList_New(0)) == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
if ((st->st_symbols = PyDict_New()) == NULL)
|
if ((st->st_symbols = PyDict_New()) == NULL)
|
||||||
|
@ -236,13 +239,18 @@ PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
|
||||||
case Suite_kind:
|
case Suite_kind:
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
"this compiler does not handle Suites");
|
"this compiler does not handle Suites");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (!symtable_exit_block(st, (void *)mod)) {
|
||||||
|
PySymtable_Free(st);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!symtable_exit_block(st, (void *)mod))
|
|
||||||
return NULL;
|
|
||||||
if (symtable_analyze(st))
|
if (symtable_analyze(st))
|
||||||
return st;
|
return st;
|
||||||
|
PySymtable_Free(st);
|
||||||
|
return NULL;
|
||||||
error:
|
error:
|
||||||
|
(void) symtable_exit_block(st, (void *)mod);
|
||||||
PySymtable_Free(st);
|
PySymtable_Free(st);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -266,15 +274,15 @@ PySymtable_Lookup(struct symtable *st, void *key)
|
||||||
v = PyDict_GetItem(st->st_symbols, k);
|
v = PyDict_GetItem(st->st_symbols, k);
|
||||||
if (v) {
|
if (v) {
|
||||||
assert(PySTEntry_Check(v));
|
assert(PySTEntry_Check(v));
|
||||||
Py_DECREF(k);
|
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
return (PySTEntryObject *)v;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyErr_SetString(PyExc_KeyError,
|
PyErr_SetString(PyExc_KeyError,
|
||||||
"unknown symbol table entry");
|
"unknown symbol table entry");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Py_DECREF(k);
|
||||||
|
return (PySTEntryObject *)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -329,8 +337,11 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name)
|
||||||
PyObject *o = PyInt_FromLong(I); \
|
PyObject *o = PyInt_FromLong(I); \
|
||||||
if (!o) \
|
if (!o) \
|
||||||
return 0; \
|
return 0; \
|
||||||
if (PyDict_SetItem((DICT), (NAME), o) < 0) \
|
if (PyDict_SetItem((DICT), (NAME), o) < 0) { \
|
||||||
|
Py_DECREF(o); \
|
||||||
return 0; \
|
return 0; \
|
||||||
|
} \
|
||||||
|
Py_DECREF(o); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decide on scope of name, given flags.
|
/* Decide on scope of name, given flags.
|
||||||
|
@ -536,6 +547,7 @@ update_symbols(PyObject *symbols, PyObject *scope,
|
||||||
Py_DECREF(free_value);
|
Py_DECREF(free_value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Py_DECREF(o);
|
||||||
}
|
}
|
||||||
/* else it's not free, probably a cell */
|
/* else it's not free, probably a cell */
|
||||||
continue;
|
continue;
|
||||||
|
@ -663,7 +675,7 @@ symtable_analyze(struct symtable *st)
|
||||||
return 0;
|
return 0;
|
||||||
global = PyDict_New();
|
global = PyDict_New();
|
||||||
if (!global) {
|
if (!global) {
|
||||||
Py_DECREF(global);
|
Py_DECREF(free);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
r = analyze_block(st->st_top, NULL, free, global);
|
r = analyze_block(st->st_top, NULL, free, global);
|
||||||
|
@ -821,6 +833,12 @@ error:
|
||||||
if (!symtable_visit_ ## TYPE((ST), (V))) \
|
if (!symtable_visit_ ## TYPE((ST), (V))) \
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#define VISIT_IN_BLOCK(ST, TYPE, V, S) \
|
||||||
|
if (!symtable_visit_ ## TYPE((ST), (V))) { \
|
||||||
|
symtable_exit_block((ST), (S)); \
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
|
|
||||||
#define VISIT_SEQ(ST, TYPE, SEQ) { \
|
#define VISIT_SEQ(ST, TYPE, SEQ) { \
|
||||||
int i; \
|
int i; \
|
||||||
asdl_seq *seq = (SEQ); /* avoid variable capture */ \
|
asdl_seq *seq = (SEQ); /* avoid variable capture */ \
|
||||||
|
@ -831,6 +849,18 @@ error:
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VISIT_SEQ_IN_BLOCK(ST, TYPE, SEQ, S) { \
|
||||||
|
int i; \
|
||||||
|
asdl_seq *seq = (SEQ); /* avoid variable capture */ \
|
||||||
|
for (i = 0; i < asdl_seq_LEN(seq); i++) { \
|
||||||
|
TYPE ## _ty elt = asdl_seq_GET(seq, i); \
|
||||||
|
if (!symtable_visit_ ## TYPE((ST), elt)) { \
|
||||||
|
symtable_exit_block((ST), (S)); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \
|
#define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \
|
||||||
int i; \
|
int i; \
|
||||||
asdl_seq *seq = (SEQ); /* avoid variable capture */ \
|
asdl_seq *seq = (SEQ); /* avoid variable capture */ \
|
||||||
|
@ -841,6 +871,18 @@ error:
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VISIT_SEQ_TAIL_IN_BLOCK(ST, TYPE, SEQ, START, S) { \
|
||||||
|
int i; \
|
||||||
|
asdl_seq *seq = (SEQ); /* avoid variable capture */ \
|
||||||
|
for (i = (START); i < asdl_seq_LEN(seq); i++) { \
|
||||||
|
TYPE ## _ty elt = asdl_seq_GET(seq, i); \
|
||||||
|
if (!symtable_visit_ ## TYPE((ST), elt)) { \
|
||||||
|
symtable_exit_block((ST), (S)); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
{
|
{
|
||||||
|
@ -855,8 +897,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
if (!symtable_enter_block(st, s->v.FunctionDef.name,
|
if (!symtable_enter_block(st, s->v.FunctionDef.name,
|
||||||
FunctionBlock, (void *)s, s->lineno))
|
FunctionBlock, (void *)s, s->lineno))
|
||||||
return 0;
|
return 0;
|
||||||
VISIT(st, arguments, s->v.FunctionDef.args);
|
VISIT_IN_BLOCK(st, arguments, s->v.FunctionDef.args, s);
|
||||||
VISIT_SEQ(st, stmt, s->v.FunctionDef.body);
|
VISIT_SEQ_IN_BLOCK(st, stmt, s->v.FunctionDef.body, s);
|
||||||
if (!symtable_exit_block(st, s))
|
if (!symtable_exit_block(st, s))
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
|
@ -870,7 +912,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
return 0;
|
return 0;
|
||||||
tmp = st->st_private;
|
tmp = st->st_private;
|
||||||
st->st_private = s->v.ClassDef.name;
|
st->st_private = s->v.ClassDef.name;
|
||||||
VISIT_SEQ(st, stmt, s->v.ClassDef.body);
|
VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s);
|
||||||
st->st_private = tmp;
|
st->st_private = tmp;
|
||||||
if (!symtable_exit_block(st, s))
|
if (!symtable_exit_block(st, s))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -977,7 +1019,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
if (cur < 0)
|
if (cur < 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (cur & (DEF_LOCAL | USE)) {
|
if (cur & (DEF_LOCAL | USE)) {
|
||||||
char buf[1000];
|
char buf[256];
|
||||||
if (cur & DEF_LOCAL)
|
if (cur & DEF_LOCAL)
|
||||||
PyOS_snprintf(buf, sizeof(buf),
|
PyOS_snprintf(buf, sizeof(buf),
|
||||||
GLOBAL_AFTER_ASSIGN,
|
GLOBAL_AFTER_ASSIGN,
|
||||||
|
@ -991,9 +1033,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
}
|
}
|
||||||
if (!symtable_add_def(st, name, DEF_GLOBAL))
|
if (!symtable_add_def(st, name, DEF_GLOBAL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Expr_kind:
|
case Expr_kind:
|
||||||
|
@ -1031,8 +1071,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||||
if (!symtable_enter_block(st, GET_IDENTIFIER(lambda),
|
if (!symtable_enter_block(st, GET_IDENTIFIER(lambda),
|
||||||
FunctionBlock, (void *)e, 0))
|
FunctionBlock, (void *)e, 0))
|
||||||
return 0;
|
return 0;
|
||||||
VISIT(st, arguments, e->v.Lambda.args);
|
VISIT_IN_BLOCK(st, arguments, e->v.Lambda.args, (void*)e);
|
||||||
VISIT(st, expr, e->v.Lambda.body);
|
VISIT_IN_BLOCK(st, expr, e->v.Lambda.body, (void*)e);
|
||||||
if (!symtable_exit_block(st, (void *)e))
|
if (!symtable_exit_block(st, (void *)e))
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
|
@ -1302,12 +1342,14 @@ symtable_visit_genexp(struct symtable *st, expr_ty e)
|
||||||
st->st_cur->ste_generator = 1;
|
st->st_cur->ste_generator = 1;
|
||||||
/* Outermost iter is received as an argument */
|
/* Outermost iter is received as an argument */
|
||||||
if (!symtable_implicit_arg(st, 0)) {
|
if (!symtable_implicit_arg(st, 0)) {
|
||||||
|
symtable_exit_block(st, (void *)e);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
VISIT(st, expr, outermost->target);
|
VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e);
|
||||||
VISIT_SEQ(st, expr, outermost->ifs);
|
VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e);
|
||||||
VISIT_SEQ_TAIL(st, comprehension, e->v.GeneratorExp.generators, 1);
|
VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension,
|
||||||
VISIT(st, expr, e->v.GeneratorExp.elt);
|
e->v.GeneratorExp.generators, 1, (void*)e);
|
||||||
|
VISIT_IN_BLOCK(st, expr, e->v.GeneratorExp.elt, (void*)e);
|
||||||
if (!symtable_exit_block(st, (void *)e))
|
if (!symtable_exit_block(st, (void *)e))
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue