https://github.com/python/cpython/commit/33605da91cfcdb88673892fef1fe2eb6fea2cde2
commit: 33605da91cfcdb88673892fef1fe2eb6fea2cde2
branch: 3.12
author: Kyle Cutler <67761731+kycut...@users.noreply.github.com>
committer: gaogaotiantian <gaogaotiant...@hotmail.com>
date: 2025-03-10T20:27:07-04:00
summary:

[3.12] gh-130809: Fix `PyFrame_LocalsToFast` copying the wrong value (#130816)

* gh-130809: Fix `PyFrame_LocalsToFast` copying the wrong value

* Skip hidden locals

* test, blurb

* Update 
Misc/NEWS.d/next/Core_and_Builtins/2025-03-04-12-52-21.gh-issue-130809.fSXq60.rst

Co-authored-by: Tian Gao <gaogaotiant...@hotmail.com>

* Update test

* PR feedback

* formatting

* comment

---------

Co-authored-by: Tian Gao <gaogaotiant...@hotmail.com>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-03-04-12-52-21.gh-issue-130809.fSXq60.rst
M Lib/test/test_listcomps.py
M Objects/frameobject.c

diff --git a/Lib/test/test_listcomps.py b/Lib/test/test_listcomps.py
index 2065afd455de5c..3e2ef1809779c3 100644
--- a/Lib/test/test_listcomps.py
+++ b/Lib/test/test_listcomps.py
@@ -709,6 +709,23 @@ def test_multiple_comprehension_name_reuse(self):
         self._check_in_scopes(code, {"x": 2, "y": [3]}, ns={"x": 3}, 
scopes=["class"])
         self._check_in_scopes(code, {"x": 2, "y": [2]}, ns={"x": 3}, 
scopes=["function", "module"])
 
+    def test_name_collision_locals(self):
+        # GH-130809: The existence of a hidden fast from list comprehension
+        # should not cause frame.f_locals on module level to return a new dict
+        # every time it is accessed.
+
+        code = """
+            import sys
+            frame = sys._getframe()
+            f_locals = frame.f_locals
+            foo = 1
+            [foo for foo in [0]]
+            # calls _PyFrame_LocalsToFast which triggers the issue
+            from abc import *
+            same_f_locals = frame.f_locals is f_locals
+        """
+        self._check_in_scopes(code, {"foo": 1, "same_f_locals": True}, 
scopes=["module"])
+
     def test_exception_locations(self):
         # The location of an exception raised from __init__ or
         # __next__ should should be the iterator expression
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-03-04-12-52-21.gh-issue-130809.fSXq60.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-04-12-52-21.gh-issue-130809.fSXq60.rst
new file mode 100644
index 00000000000000..419b2a3eb85043
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-04-12-52-21.gh-issue-130809.fSXq60.rst
@@ -0,0 +1,2 @@
+Fixed an issue where ``_PyFrame_LocalsToFast`` tries to write module level
+values to hidden fasts.
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index d33c3cde526e9f..44f2726f2ccaf1 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -1405,6 +1405,9 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int 
clear)
         if (kind & CO_FAST_FREE && !(co->co_flags & CO_OPTIMIZED)) {
             continue;
         }
+        if (kind & CO_FAST_HIDDEN) {
+            continue;
+        }
         PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
         PyObject *value = PyObject_GetItem(locals, name);
         /* We only care about NULLs if clear is true. */

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to