]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-113939: Frame clear, clear locals (#113940)
authorAlbert Zeyer <albzey@gmail.com>
Wed, 31 Jan 2024 19:14:44 +0000 (20:14 +0100)
committerGitHub <noreply@github.com>
Wed, 31 Jan 2024 19:14:44 +0000 (19:14 +0000)
Lib/test/test_frame.py
Misc/NEWS.d/next/Core and Builtins/2024-01-12-16-40-07.gh-issue-113939.Yi3L-e.rst [new file with mode: 0644]
Objects/frameobject.c

index 7f17666a8d9697b122f1fc7f70f95a1c735262ad..244ce8af7cdf088a7059f845ff4bdb2fb9a9fb89 100644 (file)
@@ -55,6 +55,28 @@ class ClearTest(unittest.TestCase):
         # The reference was released by .clear()
         self.assertIs(None, wr())
 
+    def test_clear_locals_after_f_locals_access(self):
+        # see gh-113939
+        class C:
+            pass
+
+        wr = None
+        def inner():
+            nonlocal wr
+            c = C()
+            wr = weakref.ref(c)
+            1/0
+
+        try:
+            inner()
+        except ZeroDivisionError as exc:
+            support.gc_collect()
+            self.assertIsNotNone(wr())
+            print(exc.__traceback__.tb_next.tb_frame.f_locals)
+            exc.__traceback__.tb_next.tb_frame.clear()
+            support.gc_collect()
+            self.assertIsNone(wr())
+
     def test_clear_does_not_clear_specials(self):
         class C:
             pass
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-12-16-40-07.gh-issue-113939.Yi3L-e.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-12-16-40-07.gh-issue-113939.Yi3L-e.rst
new file mode 100644 (file)
index 0000000..28b8e4b
--- /dev/null
@@ -0,0 +1,4 @@
+frame.clear():
+Clear frame.f_locals as well, and not only the fast locals.
+This is relevant once frame.f_locals was accessed,
+which would contain also references to all the locals.
index cafe4ef6141d9af620b4f417443f3cd3106d101c..a914c61aac2fd51b717e99700739e5854b4cf0f6 100644 (file)
@@ -926,6 +926,7 @@ frame_tp_clear(PyFrameObject *f)
         Py_CLEAR(locals[i]);
     }
     f->f_frame->stacktop = 0;
+    Py_CLEAR(f->f_frame->f_locals);
     return 0;
 }