From ae969fff7c82badeba0cfd4e9f4f78841d9df38e Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sun, 10 Apr 2011 07:37:26 +0300 Subject: Issue #9904: fix and clarify some comments + fix indentation in symtable code --- Python/symtable.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index 15ba6b5e2f..8040665b58 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -750,7 +750,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, goto error; } - /* Recursively call analyze_block() on each child block. + /* Recursively call analyze_child_block() on each child block. newbound, newglobal now contain the names visible in nested blocks. The free variables in the children will @@ -1205,9 +1205,9 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) case Raise_kind: if (s->v.Raise.exc) { VISIT(st, expr, s->v.Raise.exc); - if (s->v.Raise.cause) { - VISIT(st, expr, s->v.Raise.cause); - } + if (s->v.Raise.cause) { + VISIT(st, expr, s->v.Raise.cause); + } } break; case TryExcept_kind: -- cgit v1.2.1 From 21cba104ee05a4fe9df4e4b8a4424a4ac1af22a5 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 27 May 2011 13:58:08 -0500 Subject: reflect with statements with multiple items in the AST (closes #12106) --- Python/symtable.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index 8040665b58..d2762541fe 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -185,6 +185,7 @@ static int symtable_visit_params(struct symtable *st, asdl_seq *args); static int symtable_visit_argannotations(struct symtable *st, asdl_seq *args); static int symtable_implicit_arg(struct symtable *st, int pos); static int symtable_visit_annotations(struct symtable *st, stmt_ty s); +static int symtable_visit_withitem(struct symtable *st, withitem_ty item); static identifier top = NULL, lambda = NULL, genexpr = NULL, @@ -1305,10 +1306,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) /* nothing to do here */ break; case With_kind: - VISIT(st, expr, s->v.With.context_expr); - if (s->v.With.optional_vars) { - VISIT(st, expr, s->v.With.optional_vars); - } + VISIT_SEQ(st, withitem, s->v.With.items); VISIT_SEQ(st, stmt, s->v.With.body); break; } @@ -1540,6 +1538,16 @@ symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) return 1; } +static int +symtable_visit_withitem(struct symtable *st, withitem_ty item) +{ + VISIT(st, expr, item->context_expr); + if (item->optional_vars) { + VISIT(st, expr, item->optional_vars); + } + return 1; +} + static int symtable_visit_alias(struct symtable *st, alias_ty a) -- cgit v1.2.1 From 6d1f6c22f99d5c3c7df1682b77d8dc4266bc3bf3 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 29 May 2011 11:43:10 -0500 Subject: unify TryExcept and TryFinally (closes #12199) --- Python/symtable.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index d2762541fe..e31a2ebb39 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1211,14 +1211,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) } } break; - case TryExcept_kind: - VISIT_SEQ(st, stmt, s->v.TryExcept.body); - VISIT_SEQ(st, stmt, s->v.TryExcept.orelse); - VISIT_SEQ(st, excepthandler, s->v.TryExcept.handlers); - break; - case TryFinally_kind: - VISIT_SEQ(st, stmt, s->v.TryFinally.body); - VISIT_SEQ(st, stmt, s->v.TryFinally.finalbody); + case Try_kind: + VISIT_SEQ(st, stmt, s->v.Try.body); + VISIT_SEQ(st, stmt, s->v.Try.orelse); + VISIT_SEQ(st, excepthandler, s->v.Try.handlers); + VISIT_SEQ(st, stmt, s->v.Try.finalbody); break; case Assert_kind: VISIT(st, expr, s->v.Assert.test); -- cgit v1.2.1 From ffc361118f1250d4c960b2c8d0ff469de0d0b259 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 19 Jun 2011 19:42:22 -0500 Subject: use a invalid name for the __class__ closure for super() (closes #12370) This prevents the assignment of __class__ in the class body from breaking super. (Although a determined person could do locals()["@__class__"] = 4) --- Python/symtable.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index e31a2ebb39..b82d8d5b31 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -225,10 +225,17 @@ symtable_new(void) struct symtable * PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) { - struct symtable *st = symtable_new(); + struct symtable *st; asdl_seq *seq; int i; + if (__class__ == NULL) { + __class__ = PyUnicode_InternFromString("@__class__"); + if (__class__ == NULL) + return NULL; + } + + st = symtable_new(); if (st == NULL) return st; st->st_filename = filename; @@ -744,8 +751,6 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, } else { /* Special-case __class__ */ - if (!GET_IDENTIFIER(__class__)) - goto error; assert(PySet_Contains(local, __class__) == 1); if (PySet_Add(newbound, __class__) < 0) goto error; @@ -783,7 +788,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, NULL)) goto error; else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree, - "__class__")) + "@__class__")) goto error; /* Records the results of the analysis in the symbol table entry */ if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, @@ -1143,8 +1148,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, (void *)s, s->lineno, s->col_offset)) return 0; - if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, DEF_LOCAL) || + if (!symtable_add_def(st, __class__, DEF_LOCAL) || !GET_IDENTIFIER(__locals__) || !symtable_add_def(st, __locals__, DEF_PARAM)) { symtable_exit_block(st, s); @@ -1417,8 +1421,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (e->v.Name.ctx == Load && st->st_cur->ste_type == FunctionBlock && !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) { - if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, USE)) + if (!symtable_add_def(st, __class__, USE)) return 0; } break; -- cgit v1.2.1 From 08ea9b8b20b6fb77e2fca3026bca7301b2829e38 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 29 Jun 2011 15:27:14 -0500 Subject: remove VISIT_*_IN_BLOCK macros These are pointless because on error, all blocks will be finalized by symtable_dealloc. --- Python/symtable.c | 51 ++++++++++----------------------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index 232f02c500..f86575bdf4 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1029,12 +1029,6 @@ error: if (!symtable_visit_ ## TYPE((ST), (V))) \ 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) { \ int i; \ asdl_seq *seq = (SEQ); /* avoid variable capture */ \ @@ -1045,18 +1039,6 @@ 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 = (TYPE ## _ty)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) { \ int i; \ asdl_seq *seq = (SEQ); /* avoid variable capture */ \ @@ -1067,18 +1049,6 @@ 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 = (TYPE ## _ty)asdl_seq_GET(seq, i); \ - if (!symtable_visit_ ## TYPE((ST), elt)) { \ - symtable_exit_block((ST), (S)); \ - return 0; \ - } \ - } \ -} - #define VISIT_KWONLYDEFAULTS(ST, KW_DEFAULTS) { \ int i = 0; \ asdl_seq *seq = (KW_DEFAULTS); /* avoid variable capture */ \ @@ -1128,8 +1098,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) FunctionBlock, (void *)s, s->lineno, s->col_offset)) return 0; - VISIT_IN_BLOCK(st, arguments, s->v.FunctionDef.args, s); - VISIT_SEQ_IN_BLOCK(st, stmt, s->v.FunctionDef.body, s); + VISIT(st, arguments, s->v.FunctionDef.args); + VISIT_SEQ(st, stmt, s->v.FunctionDef.body); if (!symtable_exit_block(st, s)) return 0; break; @@ -1156,7 +1126,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) } tmp = st->st_private; st->st_private = s->v.ClassDef.name; - VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s); + VISIT_SEQ(st, stmt, s->v.ClassDef.body); st->st_private = tmp; if (!symtable_exit_block(st, s)) return 0; @@ -1337,8 +1307,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e) FunctionBlock, (void *)e, e->lineno, e->col_offset)) return 0; - VISIT_IN_BLOCK(st, arguments, e->v.Lambda.args, (void*)e); - VISIT_IN_BLOCK(st, expr, e->v.Lambda.body, (void*)e); + VISIT(st, arguments, e->v.Lambda.args); + VISIT(st, expr, e->v.Lambda.body); if (!symtable_exit_block(st, (void *)e)) return 0; break; @@ -1658,13 +1628,12 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, symtable_exit_block(st, (void *)e); return 0; } - VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e); - VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e); - VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension, - generators, 1, (void*)e); + VISIT(st, expr, outermost->target); + VISIT_SEQ(st, expr, outermost->ifs); + VISIT_SEQ_TAIL(st, comprehension, generators, 1); if (value) - VISIT_IN_BLOCK(st, expr, value, (void*)e); - VISIT_IN_BLOCK(st, expr, elt, (void*)e); + VISIT(st, expr, value); + VISIT(st, expr, elt); return symtable_exit_block(st, (void *)e); } -- cgit v1.2.1 From 507a021f5a83b200f01f531ab6a819a7134bc0cb Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 29 Jun 2011 22:52:39 -0500 Subject: store the current scope on the stack right away --- Python/symtable.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index f86575bdf4..82b1ebb7fa 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -899,17 +899,14 @@ symtable_warn(struct symtable *st, char *msg, int lineno) static int symtable_exit_block(struct symtable *st, void *ast) { - Py_ssize_t end; + Py_ssize_t size; - Py_CLEAR(st->st_cur); - end = PyList_GET_SIZE(st->st_stack) - 1; - if (end >= 0) { + st->st_cur = NULL; + size = PyList_GET_SIZE(st->st_stack); + if (size) { st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, - end); - if (st->st_cur == NULL) - return 0; - Py_INCREF(st->st_cur); - if (PySequence_DelItem(st->st_stack, end) < 0) + size - 2); + if (PyList_SetSlice(st->st_stack, size - 1, size, NULL) < 0) return 0; } return 1; @@ -919,23 +916,23 @@ static int symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, void *ast, int lineno, int col_offset) { - PySTEntryObject *prev = NULL; + PySTEntryObject *prev = NULL, *ste; - if (st->st_cur) { - prev = st->st_cur; - if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) { - return 0; - } - Py_DECREF(st->st_cur); - } - st->st_cur = ste_new(st, name, block, ast, lineno, col_offset); - if (st->st_cur == NULL) + ste = ste_new(st, name, block, ast, lineno, col_offset); + if (ste == NULL) return 0; + if (PyList_Append(st->st_stack, (PyObject *)ste) < 0) { + Py_DECREF(ste); + return 0; + } + prev = st->st_cur; + /* The entry is owned by the stack. Borrow it for st_cur. */ + Py_DECREF(ste); + st->st_cur = ste; if (block == ModuleBlock) st->st_global = st->st_cur->ste_symbols; if (prev) { - if (PyList_Append(prev->ste_children, - (PyObject *)st->st_cur) < 0) { + if (PyList_Append(prev->ste_children, (PyObject *)ste) < 0) { return 0; } } -- cgit v1.2.1 From 0c131a7b4cff5aa25bb4fd1757e4874efb4523f6 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 2 Jul 2011 09:22:13 -0500 Subject: fix possibily uninitialized memory usage (closes #12474) --- Python/symtable.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index 82b1ebb7fa..a0bedfc767 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -904,10 +904,10 @@ symtable_exit_block(struct symtable *st, void *ast) st->st_cur = NULL; size = PyList_GET_SIZE(st->st_stack); if (size) { - st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, - size - 2); if (PyList_SetSlice(st->st_stack, size - 1, size, NULL) < 0) return 0; + if (--size) + st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, size - 1); } return 1; } -- cgit v1.2.1 From d1d013c01c268d869597b35cbcd8b5d7c5baf2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Wed, 28 Sep 2011 07:41:54 +0200 Subject: Implement PEP 393. --- Python/symtable.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index a0bedfc767..3578b0c692 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1525,10 +1525,10 @@ symtable_visit_alias(struct symtable *st, alias_ty a) */ PyObject *store_name; PyObject *name = (a->asname == NULL) ? a->name : a->asname; - const Py_UNICODE *base = PyUnicode_AS_UNICODE(name); - Py_UNICODE *dot = Py_UNICODE_strchr(base, '.'); - if (dot) { - store_name = PyUnicode_FromUnicode(base, dot - base); + Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, + PyUnicode_GET_LENGTH(name), 1); + if (dot != -1) { + store_name = PyUnicode_Substring(name, 0, dot); if (!store_name) return 0; } -- cgit v1.2.1 From e4f5fc423651e760f014159dce83273f9d54831c Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Fri, 13 Jan 2012 21:43:40 +1000 Subject: Implement PEP 380 - 'yield from' (closes #11682) --- Python/symtable.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index 824a53fc1b..1ce7f7036f 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -19,10 +19,6 @@ #define IMPORT_STAR_WARNING "import * only allowed at module level" -#define RETURN_VAL_IN_GENERATOR \ - "'return' with argument inside generator" - - static PySTEntryObject * ste_new(struct symtable *st, identifier name, _Py_block_ty block, void *key, int lineno, int col_offset) @@ -1133,14 +1129,6 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (s->v.Return.value) { VISIT(st, expr, s->v.Return.value); st->st_cur->ste_returns_value = 1; - if (st->st_cur->ste_generator) { - PyErr_SetString(PyExc_SyntaxError, - RETURN_VAL_IN_GENERATOR); - PyErr_SyntaxLocationEx(st->st_filename, - s->lineno, - s->col_offset); - return 0; - } } break; case Delete_kind: @@ -1345,13 +1333,6 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (e->v.Yield.value) VISIT(st, expr, e->v.Yield.value); st->st_cur->ste_generator = 1; - if (st->st_cur->ste_returns_value) { - PyErr_SetString(PyExc_SyntaxError, - RETURN_VAL_IN_GENERATOR); - PyErr_SyntaxLocationEx(st->st_filename, - e->lineno, e->col_offset); - return 0; - } break; case Compare_kind: VISIT(st, expr, e->v.Compare.left); -- cgit v1.2.1 From 37fe2bd5e9be127591b1e39efe50fc0c3348b5ab Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 14 Jan 2012 08:58:23 -0500 Subject: make YieldFrom its own distinct from Yield (closes #13780) --- Python/symtable.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index 1ce7f7036f..b6228356bf 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1330,10 +1330,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e) return 0; break; case Yield_kind: - if (e->v.Yield.value) - VISIT(st, expr, e->v.Yield.value); + case YieldFrom_kind: { + expr_ty value; + value = (e->kind == YieldFrom_kind) ? e->v.YieldFrom.value : e->v.Yield.value; + if (value) + VISIT(st, expr, value); st->st_cur->ste_generator = 1; break; + } case Compare_kind: VISIT(st, expr, e->v.Compare.left); VISIT_SEQ(st, expr, e->v.Compare.comparators); -- cgit v1.2.1 From e26eba13bcc570d5e912886692d5030db7b74ac3 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sun, 27 May 2012 18:17:07 +1000 Subject: Close #14857: fix regression in references to PEP 3135 implicit __class__ closure variable. Reopens issue #12370, but also updates unittest.mock to workaround that issue --- Python/symtable.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index b6228356bf..a0b786b3d7 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -221,17 +221,10 @@ symtable_new(void) struct symtable * PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) { - struct symtable *st; + struct symtable *st = symtable_new(); asdl_seq *seq; int i; - if (__class__ == NULL) { - __class__ = PyUnicode_InternFromString("@__class__"); - if (__class__ == NULL) - return NULL; - } - - st = symtable_new(); if (st == NULL) return st; st->st_filename = filename; @@ -747,6 +740,8 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, } else { /* Special-case __class__ */ + if (!GET_IDENTIFIER(__class__)) + goto error; assert(PySet_Contains(local, __class__) == 1); if (PySet_Add(newbound, __class__) < 0) goto error; @@ -784,7 +779,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, NULL)) goto error; else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree, - "@__class__")) + "__class__")) goto error; /* Records the results of the analysis in the symbol table entry */ if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, @@ -1111,7 +1106,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, (void *)s, s->lineno, s->col_offset)) return 0; - if (!symtable_add_def(st, __class__, DEF_LOCAL) || + if (!GET_IDENTIFIER(__class__) || + !symtable_add_def(st, __class__, DEF_LOCAL) || !GET_IDENTIFIER(__locals__) || !symtable_add_def(st, __locals__, DEF_PARAM)) { symtable_exit_block(st, s); @@ -1376,7 +1372,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (e->v.Name.ctx == Load && st->st_cur->ste_type == FunctionBlock && !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) { - if (!symtable_add_def(st, __class__, USE)) + if (!GET_IDENTIFIER(__class__) || + !symtable_add_def(st, __class__, USE)) return 0; } break; -- cgit v1.2.1 From 8144eb153a29e607aa5ee1957e1723557f605ae6 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 31 Oct 2012 19:01:42 -0400 Subject: check return value of _PyUnicode_AsString --- Python/symtable.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index 1c291bbac0..ff6e8b79b9 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1202,12 +1202,14 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) asdl_seq *seq = s->v.Global.names; for (i = 0; i < asdl_seq_LEN(seq); i++) { identifier name = (identifier)asdl_seq_GET(seq, i); - char *c_name = _PyUnicode_AsString(name); long cur = symtable_lookup(st, name); if (cur < 0) return 0; if (cur & (DEF_LOCAL | USE)) { char buf[256]; + char *c_name = _PyUnicode_AsString(name); + if (!c_name) + return 0; if (cur & DEF_LOCAL) PyOS_snprintf(buf, sizeof(buf), GLOBAL_AFTER_ASSIGN, @@ -1229,12 +1231,14 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) asdl_seq *seq = s->v.Nonlocal.names; for (i = 0; i < asdl_seq_LEN(seq); i++) { identifier name = (identifier)asdl_seq_GET(seq, i); - char *c_name = _PyUnicode_AsString(name); long cur = symtable_lookup(st, name); if (cur < 0) return 0; if (cur & (DEF_LOCAL | USE)) { char buf[256]; + char *c_name = _PyUnicode_AsString(name); + if (!c_name) + return 0; if (cur & DEF_LOCAL) PyOS_snprintf(buf, sizeof(buf), NONLOCAL_AFTER_ASSIGN, -- cgit v1.2.1 From edcdaaa21d40a48b0fad3672f9a532534b935152 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sun, 4 Nov 2012 23:14:34 +1000 Subject: Issue #5765: Apply a hard recursion limit in the compiler Previously, excessive nesting in expressions would blow the stack and segfault the interpreter. Now, a hard limit based on the configured recursion limit and a hardcoded scaling factor is applied. --- Python/symtable.c | 97 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 29 deletions(-) (limited to 'Python/symtable.c') diff --git a/Python/symtable.c b/Python/symtable.c index ff6e8b79b9..9dde908832 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -220,17 +220,40 @@ symtable_new(void) return NULL; } +/* When compiling the use of C stack is probably going to be a lot + lighter than when executing Python code but still can overflow + and causing a Python crash if not checked (e.g. eval("()"*300000)). + Using the current recursion limit for the compiler seems too + restrictive (it caused at least one test to fail) so a factor is + used to allow deeper recursion when compiling an expression. + + Using a scaling factor means this should automatically adjust when + the recursion limit is adjusted for small or large C stack allocations. +*/ +#define COMPILER_STACK_FRAME_SCALE 3 + struct symtable * PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) { struct symtable *st = symtable_new(); asdl_seq *seq; int i; + PyThreadState *tstate; if (st == NULL) return st; st->st_filename = filename; st->st_future = future; + + /* Setup recursion depth check counters */ + tstate = PyThreadState_GET(); + if (!tstate) { + PySymtable_Free(st); + return NULL; + } + st->recursion_depth = tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE; + st->recursion_limit = Py_GetRecursionLimit() * COMPILER_STACK_FRAME_SCALE; + /* Make the initial symbol information gathering pass */ if (!GET_IDENTIFIER(top) || !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0, 0)) { @@ -1013,11 +1036,17 @@ error: VISIT_SEQ_TAIL permits the start of an ASDL sequence to be skipped, which is useful if the first node in the sequence requires special treatment. + + VISIT_QUIT macro returns the specified value exiting from the function but + first adjusts current recursion counter depth. */ +#define VISIT_QUIT(ST, X) \ + return --(ST)->recursion_depth,(X) + #define VISIT(ST, TYPE, V) \ if (!symtable_visit_ ## TYPE((ST), (V))) \ - return 0; + VISIT_QUIT((ST), 0); #define VISIT_SEQ(ST, TYPE, SEQ) { \ int i; \ @@ -1025,7 +1054,7 @@ error: for (i = 0; i < asdl_seq_LEN(seq); i++) { \ TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ if (!symtable_visit_ ## TYPE((ST), elt)) \ - return 0; \ + VISIT_QUIT((ST), 0); \ } \ } @@ -1035,7 +1064,7 @@ error: for (i = (START); i < asdl_seq_LEN(seq); i++) { \ TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ if (!symtable_visit_ ## TYPE((ST), elt)) \ - return 0; \ + VISIT_QUIT((ST), 0); \ } \ } @@ -1046,7 +1075,7 @@ error: expr_ty elt = (expr_ty)asdl_seq_GET(seq, i); \ if (!elt) continue; /* can be NULL */ \ if (!symtable_visit_expr((ST), elt)) \ - return 0; \ + VISIT_QUIT((ST), 0); \ } \ } @@ -1071,32 +1100,37 @@ symtable_new_tmpname(struct symtable *st) static int symtable_visit_stmt(struct symtable *st, stmt_ty s) { + if (++st->recursion_depth > st->recursion_limit) { + PyErr_SetString(PyExc_RuntimeError, + "maximum recursion depth exceeded during compilation"); + VISIT_QUIT(st, 0); + } switch (s->kind) { case FunctionDef_kind: if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL)) - return 0; + VISIT_QUIT(st, 0); if (s->v.FunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); if (s->v.FunctionDef.args->kw_defaults) VISIT_KWONLYDEFAULTS(st, s->v.FunctionDef.args->kw_defaults); if (!symtable_visit_annotations(st, s)) - return 0; + VISIT_QUIT(st, 0); if (s->v.FunctionDef.decorator_list) VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); if (!symtable_enter_block(st, s->v.FunctionDef.name, FunctionBlock, (void *)s, s->lineno, s->col_offset)) - return 0; + VISIT_QUIT(st, 0); VISIT(st, arguments, s->v.FunctionDef.args); VISIT_SEQ(st, stmt, s->v.FunctionDef.body); if (!symtable_exit_block(st, s)) - return 0; + VISIT_QUIT(st, 0); break; case ClassDef_kind: { PyObject *tmp; if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) - return 0; + VISIT_QUIT(st, 0); VISIT_SEQ(st, expr, s->v.ClassDef.bases); VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); if (s->v.ClassDef.starargs) @@ -1107,20 +1141,20 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list); if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, (void *)s, s->lineno, s->col_offset)) - return 0; + VISIT_QUIT(st, 0); if (!GET_IDENTIFIER(__class__) || !symtable_add_def(st, __class__, DEF_LOCAL) || !GET_IDENTIFIER(__locals__) || !symtable_add_def(st, __locals__, DEF_PARAM)) { symtable_exit_block(st, s); - return 0; + VISIT_QUIT(st, 0); } tmp = st->st_private; st->st_private = s->v.ClassDef.name; VISIT_SEQ(st, stmt, s->v.ClassDef.body); st->st_private = tmp; if (!symtable_exit_block(st, s)) - return 0; + VISIT_QUIT(st, 0); break; } case Return_kind: @@ -1204,7 +1238,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) identifier name = (identifier)asdl_seq_GET(seq, i); long cur = symtable_lookup(st, name); if (cur < 0) - return 0; + VISIT_QUIT(st, 0); if (cur & (DEF_LOCAL | USE)) { char buf[256]; char *c_name = _PyUnicode_AsString(name); @@ -1219,10 +1253,10 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) GLOBAL_AFTER_USE, c_name); if (!symtable_warn(st, buf, s->lineno)) - return 0; + VISIT_QUIT(st, 0); } if (!symtable_add_def(st, name, DEF_GLOBAL)) - return 0; + VISIT_QUIT(st, 0); } break; } @@ -1233,7 +1267,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) identifier name = (identifier)asdl_seq_GET(seq, i); long cur = symtable_lookup(st, name); if (cur < 0) - return 0; + VISIT_QUIT(st, 0); if (cur & (DEF_LOCAL | USE)) { char buf[256]; char *c_name = _PyUnicode_AsString(name); @@ -1248,10 +1282,10 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) NONLOCAL_AFTER_USE, c_name); if (!symtable_warn(st, buf, s->lineno)) - return 0; + VISIT_QUIT(st, 0); } if (!symtable_add_def(st, name, DEF_NONLOCAL)) - return 0; + VISIT_QUIT(st, 0); } break; } @@ -1268,12 +1302,17 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, stmt, s->v.With.body); break; } - return 1; + VISIT_QUIT(st, 1); } static int symtable_visit_expr(struct symtable *st, expr_ty e) { + if (++st->recursion_depth > st->recursion_limit) { + PyErr_SetString(PyExc_RuntimeError, + "maximum recursion depth exceeded during compilation"); + VISIT_QUIT(st, 0); + } switch (e->kind) { case BoolOp_kind: VISIT_SEQ(st, expr, e->v.BoolOp.values); @@ -1287,7 +1326,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) break; case Lambda_kind: { if (!GET_IDENTIFIER(lambda)) - return 0; + VISIT_QUIT(st, 0); if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); if (e->v.Lambda.args->kw_defaults) @@ -1296,11 +1335,11 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (!symtable_enter_block(st, lambda, FunctionBlock, (void *)e, e->lineno, e->col_offset)) - return 0; + VISIT_QUIT(st, 0); VISIT(st, arguments, e->v.Lambda.args); VISIT(st, expr, e->v.Lambda.body); if (!symtable_exit_block(st, (void *)e)) - return 0; + VISIT_QUIT(st, 0); break; } case IfExp_kind: @@ -1317,19 +1356,19 @@ symtable_visit_expr(struct symtable *st, expr_ty e) break; case GeneratorExp_kind: if (!symtable_visit_genexp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case ListComp_kind: if (!symtable_visit_listcomp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case SetComp_kind: if (!symtable_visit_setcomp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case DictComp_kind: if (!symtable_visit_dictcomp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case Yield_kind: case YieldFrom_kind: { @@ -1373,14 +1412,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e) case Name_kind: if (!symtable_add_def(st, e->v.Name.id, e->v.Name.ctx == Load ? USE : DEF_LOCAL)) - return 0; + VISIT_QUIT(st, 0); /* Special-case super: it counts as a use of __class__ */ if (e->v.Name.ctx == Load && st->st_cur->ste_type == FunctionBlock && !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) { if (!GET_IDENTIFIER(__class__) || !symtable_add_def(st, __class__, USE)) - return 0; + VISIT_QUIT(st, 0); } break; /* child nodes of List and Tuple will have expr_context set */ @@ -1391,7 +1430,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT_SEQ(st, expr, e->v.Tuple.elts); break; } - return 1; + VISIT_QUIT(st, 1); } static int -- cgit v1.2.1