From 3cc8f4b9693572e6ea423881cdbebfc981307b50 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 29 Dec 2015 10:08:34 -0600 Subject: [PATCH] make recording and reporting errors and nonlocal and global directives more robust (closes #25973) --- Lib/test/test_syntax.py | 8 ++++++++ Misc/NEWS | 3 +++ Python/symtable.c | 24 ++++++++++++++++-------- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index a22cebb828b..057441c83c0 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -416,6 +416,14 @@ TODO(jhylton): Figure out how to test SyntaxWarning with doctest. ## ... ## SyntaxWarning: name 'x' is assigned to before nonlocal declaration + From https://bugs.python.org/issue25973 + >>> class A: + ... def f(self): + ... nonlocal __x + Traceback (most recent call last): + ... + SyntaxError: no binding for nonlocal '_A__x' found + This tests assignment-context; there was a bug in Python 2.5 where compiling a complex 'if' (one with 'elif') would fail to notice an invalid suite, diff --git a/Misc/NEWS b/Misc/NEWS index bb0e0568f5d..0421c0a363d 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Release date: tba Core and Builtins ----------------- +- Issue #25973: Fix segfault when an invalid nonlocal statement binds a name + starting with two underscores. + - Issue #22995: Instances of extension types with a state that aren't subclasses of list or dict and haven't implemented any pickle-related methods (__reduce__, __reduce_ex__, __getnewargs__, __getnewargs_ex__, diff --git a/Python/symtable.c b/Python/symtable.c index 64910d8a558..6d1a62b7824 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -368,15 +368,20 @@ error_at_directive(PySTEntryObject *ste, PyObject *name) Py_ssize_t i; PyObject *data; assert(ste->ste_directives); - for (i = 0; ; i++) { + for (i = 0; i < PyList_GET_SIZE(ste->ste_directives); i++) { data = PyList_GET_ITEM(ste->ste_directives, i); assert(PyTuple_CheckExact(data)); - if (PyTuple_GET_ITEM(data, 0) == name) - break; + assert(PyUnicode_CheckExact(PyTuple_GET_ITEM(data, 0))); + if (PyUnicode_Compare(PyTuple_GET_ITEM(data, 0), name) == 0) { + PyErr_SyntaxLocationObject(ste->ste_table->st_filename, + PyLong_AsLong(PyTuple_GET_ITEM(data, 1)), + PyLong_AsLong(PyTuple_GET_ITEM(data, 2))); + + return 0; + } } - PyErr_SyntaxLocationObject(ste->ste_table->st_filename, - PyLong_AsLong(PyTuple_GET_ITEM(data, 1)), - PyLong_AsLong(PyTuple_GET_ITEM(data, 2))); + PyErr_SetString(PyExc_RuntimeError, + "BUG: internal directive bookkeeping broken"); return 0; } @@ -1115,14 +1120,17 @@ symtable_new_tmpname(struct symtable *st) static int symtable_record_directive(struct symtable *st, identifier name, stmt_ty s) { - PyObject *data; + PyObject *data, *mangled; int res; if (!st->st_cur->ste_directives) { st->st_cur->ste_directives = PyList_New(0); if (!st->st_cur->ste_directives) return 0; } - data = Py_BuildValue("(Oii)", name, s->lineno, s->col_offset); + mangled = _Py_Mangle(st->st_private, name); + if (!mangled) + return 0; + data = Py_BuildValue("(Nii)", mangled, s->lineno, s->col_offset); if (!data) return 0; res = PyList_Append(st->st_cur->ste_directives, data);