]> granicus.if.org Git - python/commitdiff
make recording and reporting errors and nonlocal and global directives more robust...
authorBenjamin Peterson <benjamin@python.org>
Tue, 29 Dec 2015 16:08:34 +0000 (10:08 -0600)
committerBenjamin Peterson <benjamin@python.org>
Tue, 29 Dec 2015 16:08:34 +0000 (10:08 -0600)
Lib/test/test_syntax.py
Misc/NEWS
Python/symtable.c

index a22cebb828b3d40975bf07f093360a7f8f01a137..057441c83c0f7109a3d7565efb4359836533dbd5 100644 (file)
@@ -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,
index bb0e0568f5d02b46721759af2b65797ca7df55a3..0421c0a363d24411cc091abb45b3bc181d09248d 100644 (file)
--- 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__,
index 64910d8a558b776408b057389ebe4df259ddd8ac..6d1a62b782465d521052d3cf393e2368af4e0283 100644 (file)
@@ -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);