]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-128396: Fix a crash when inline comprehension has the same local variable as the...
authorTian Gao <gaogaotiantian@hotmail.com>
Wed, 19 Feb 2025 17:11:17 +0000 (12:11 -0500)
committerGitHub <noreply@github.com>
Wed, 19 Feb 2025 17:11:17 +0000 (12:11 -0500)
Lib/test/test_frame.py
Misc/NEWS.d/next/Core_and_Builtins/2025-02-17-18-59-33.gh-issue-128396.iVtoYY.rst [new file with mode: 0644]
Objects/frameobject.c

index 4d086064023488ba97156d81a0a3d3089bb412ba..a6e11f1a5342b633b4e93283d92268eb320389cd 100644 (file)
@@ -346,6 +346,12 @@ class TestFrameLocals(unittest.TestCase):
         self.assertEqual(x, 2)
         self.assertEqual(y, 3)
 
+    def test_closure_with_inline_comprehension(self):
+        lambda: k
+        k = 1
+        lst = [locals() for k in [0]]
+        self.assertEqual(lst[0]['k'], 0)
+
     def test_as_dict(self):
         x = 1
         y = 2
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-17-18-59-33.gh-issue-128396.iVtoYY.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-17-18-59-33.gh-issue-128396.iVtoYY.rst
new file mode 100644 (file)
index 0000000..4382b77
--- /dev/null
@@ -0,0 +1 @@
+Fix a crash that occurs when calling :func:`locals` inside an inline comprehension that uses the same local variable as the outer frame scope where the variable is a free or cell var.
index 8ebcc1a4b5e8922ecabfdbaf4aaf05ceba3a2baf..dbeee50fcff0904e843f5498b17e191358c0d87d 100644 (file)
@@ -45,8 +45,15 @@ framelocalsproxy_getval(_PyInterpreterFrame *frame, PyCodeObject *co, int i)
     if (kind == CO_FAST_FREE || kind & CO_FAST_CELL) {
         // The cell was set when the frame was created from
         // the function's closure.
-        assert(PyCell_Check(value));
-        cell = value;
+        // GH-128396: With PEP 709, it's possible to have a fast variable in
+        // an inlined comprehension that has the same name as the cell variable
+        // in the frame, where the `kind` obtained from frame can not guarantee
+        // that the variable is a cell.
+        // If the variable is not a cell, we are okay with it and we can simply
+        // return the value.
+        if (PyCell_Check(value)) {
+            cell = value;
+        }
     }
 
     if (cell != NULL) {