Commit 3cc8f4b9 authored by Benjamin Peterson's avatar Benjamin Peterson

make recording and reporting errors and nonlocal and global directives more robust (closes #25973)

parent 01f7ac3b
...@@ -416,6 +416,14 @@ TODO(jhylton): Figure out how to test SyntaxWarning with doctest. ...@@ -416,6 +416,14 @@ TODO(jhylton): Figure out how to test SyntaxWarning with doctest.
## ... ## ...
## SyntaxWarning: name 'x' is assigned to before nonlocal declaration ## 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 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, a complex 'if' (one with 'elif') would fail to notice an invalid suite,
......
...@@ -10,6 +10,9 @@ Release date: tba ...@@ -10,6 +10,9 @@ Release date: tba
Core and Builtins 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 - Issue #22995: Instances of extension types with a state that aren't
subclasses of list or dict and haven't implemented any pickle-related subclasses of list or dict and haven't implemented any pickle-related
methods (__reduce__, __reduce_ex__, __getnewargs__, __getnewargs_ex__, methods (__reduce__, __reduce_ex__, __getnewargs__, __getnewargs_ex__,
......
...@@ -368,15 +368,20 @@ error_at_directive(PySTEntryObject *ste, PyObject *name) ...@@ -368,15 +368,20 @@ error_at_directive(PySTEntryObject *ste, PyObject *name)
Py_ssize_t i; Py_ssize_t i;
PyObject *data; PyObject *data;
assert(ste->ste_directives); 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); data = PyList_GET_ITEM(ste->ste_directives, i);
assert(PyTuple_CheckExact(data)); assert(PyTuple_CheckExact(data));
if (PyTuple_GET_ITEM(data, 0) == name) assert(PyUnicode_CheckExact(PyTuple_GET_ITEM(data, 0)));
break; 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, PyErr_SetString(PyExc_RuntimeError,
PyLong_AsLong(PyTuple_GET_ITEM(data, 1)), "BUG: internal directive bookkeeping broken");
PyLong_AsLong(PyTuple_GET_ITEM(data, 2)));
return 0; return 0;
} }
...@@ -1115,14 +1120,17 @@ symtable_new_tmpname(struct symtable *st) ...@@ -1115,14 +1120,17 @@ symtable_new_tmpname(struct symtable *st)
static int static int
symtable_record_directive(struct symtable *st, identifier name, stmt_ty s) symtable_record_directive(struct symtable *st, identifier name, stmt_ty s)
{ {
PyObject *data; PyObject *data, *mangled;
int res; int res;
if (!st->st_cur->ste_directives) { if (!st->st_cur->ste_directives) {
st->st_cur->ste_directives = PyList_New(0); st->st_cur->ste_directives = PyList_New(0);
if (!st->st_cur->ste_directives) if (!st->st_cur->ste_directives)
return 0; 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) if (!data)
return 0; return 0;
res = PyList_Append(st->st_cur->ste_directives, data); res = PyList_Append(st->st_cur->ste_directives, data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment