]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-96497: Mangle name before symtable lookup in 'symtable_extend_namedexpr_sco...
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 17 Feb 2024 13:13:26 +0000 (15:13 +0200)
committerGitHub <noreply@github.com>
Sat, 17 Feb 2024 13:13:26 +0000 (13:13 +0000)
(cherry picked from commit 664965a1c141e8af5eb465d29099781a6a2fc3f3)

Co-authored-by: wookie184 <wookie1840@gmail.com>
Lib/test/test_named_expressions.py
Misc/NEWS.d/next/Core and Builtins/2022-09-04-16-51-56.gh-issue-96497.HTBuIL.rst [new file with mode: 0644]
Python/symtable.c

index 20ac2e699f0c35bc4917a799dda6c09578312c7a..cfb6549b83004eb26f0eff9ced25c6e4b9c4a540 100644 (file)
@@ -222,6 +222,16 @@ class NamedExpressionInvalidTest(unittest.TestCase):
                 with self.assertRaisesRegex(SyntaxError, msg):
                     exec(f"lambda: {code}", {}) # Function scope
 
+    def test_named_expression_invalid_mangled_class_variables(self):
+        code = """class Foo:
+            def bar(self):
+                [[(__x:=2) for _ in range(2)] for __x in range(2)]
+        """
+
+        with self.assertRaisesRegex(SyntaxError,
+            "assignment expression cannot rebind comprehension iteration variable '__x'"):
+            exec(code, {}, {})
+
 
 class NamedExpressionAssignmentTest(unittest.TestCase):
 
@@ -598,6 +608,18 @@ spam()"""
         for idx, elem in enumerate(genexp):
             self.assertEqual(elem, b[idx] + a)
 
+    def test_named_expression_scope_mangled_names(self):
+        class Foo:
+            def f(self_):
+                global __x1
+                __x1 = 0
+                [_Foo__x1 := 1 for a in [2]]
+                self.assertEqual(__x1, 1)
+                [__x1 := 2 for a in [3]]
+                self.assertEqual(__x1, 2)
+
+        Foo().f()
+        self.assertEqual(_Foo__x1, 2)
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-04-16-51-56.gh-issue-96497.HTBuIL.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-04-16-51-56.gh-issue-96497.HTBuIL.rst
new file mode 100644 (file)
index 0000000..6881dde
--- /dev/null
@@ -0,0 +1,2 @@
+Fix incorrect resolution of mangled class variables used in assignment
+expressions in comprehensions.
index 3519f62098425cef0fd157a60e40f9f5e31e7e51..03257b7af3bb2a95e5a27f41f5a30d0d13ad2e4c 100644 (file)
@@ -1042,16 +1042,22 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
 }
 
 static long
-symtable_lookup(struct symtable *st, PyObject *name)
+symtable_lookup_entry(struct symtable *st, PySTEntryObject *ste, PyObject *name)
 {
     PyObject *mangled = _Py_Mangle(st->st_private, name);
     if (!mangled)
         return 0;
-    long ret = _PyST_GetSymbol(st->st_cur, mangled);
+    long ret = _PyST_GetSymbol(ste, mangled);
     Py_DECREF(mangled);
     return ret;
 }
 
+static long
+symtable_lookup(struct symtable *st, PyObject *name)
+{
+    return symtable_lookup_entry(st, st->st_cur, name);
+}
+
 static int
 symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _symtable_entry *ste,
                         int lineno, int col_offset, int end_lineno, int end_col_offset)
@@ -1525,7 +1531,7 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
          * binding conflict with iteration variables, otherwise skip it
          */
         if (ste->ste_comprehension) {
-            long target_in_scope = _PyST_GetSymbol(ste, target_name);
+            long target_in_scope = symtable_lookup_entry(st, ste, target_name);
             if (target_in_scope & DEF_COMP_ITER) {
                 PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_CONFLICT, target_name);
                 PyErr_RangedSyntaxLocationObject(st->st_filename,
@@ -1540,7 +1546,7 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
 
         /* If we find a FunctionBlock entry, add as GLOBAL/LOCAL or NONLOCAL/LOCAL */
         if (ste->ste_type == FunctionBlock) {
-            long target_in_scope = _PyST_GetSymbol(ste, target_name);
+            long target_in_scope = symtable_lookup_entry(st, ste, target_name);
             if (target_in_scope & DEF_GLOBAL) {
                 if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e)))
                     VISIT_QUIT(st, 0);