[Python-checkins] Do not clear globals or builtins when calling clear() on a frame object. Reverts behavior to that of 3.10 and earlier. (GH-26768)

markshannon webhook-mailer at python.org
Thu Jun 17 11:29:20 EDT 2021


https://github.com/python/cpython/commit/ba2f32a983a08c4f64c23c187432e38908639c12
commit: ba2f32a983a08c4f64c23c187432e38908639c12
branch: main
author: Mark Shannon <mark at hotpy.org>
committer: markshannon <mark at hotpy.org>
date: 2021-06-17T16:29:15+01:00
summary:

Do not clear globals or builtins when calling clear() on a frame object. Reverts behavior to that of 3.10 and earlier. (GH-26768)

files:
M Lib/test/test_frame.py
M Objects/frameobject.c

diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py
index 7ac37b6937502..a715e725a7e45 100644
--- a/Lib/test/test_frame.py
+++ b/Lib/test/test_frame.py
@@ -45,6 +45,19 @@ class C:
         # The reference was released by .clear()
         self.assertIs(None, wr())
 
+    def test_clear_does_not_clear_specials(self):
+        class C:
+            pass
+        c = C()
+        exc = self.outer(c=c)
+        del c
+        f = exc.__traceback__.tb_frame
+        f.clear()
+        self.assertIsNot(f.f_code, None)
+        self.assertIsNot(f.f_locals, None)
+        self.assertIsNot(f.f_builtins, None)
+        self.assertIsNot(f.f_globals, None)
+
     def test_clear_generator(self):
         endly = False
         def g():
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 99afe06d81636..5057313870c60 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -612,7 +612,7 @@ frame_dealloc(PyFrameObject *f)
     Py_TRASHCAN_SAFE_BEGIN(f)
     PyCodeObject *co = f->f_code;
 
-    /* Kill all local variables */
+    /* Kill all local variables including specials. */
     if (f->f_localsptr) {
         for (int i = 0; i < co->co_nlocalsplus+FRAME_SPECIALS_SIZE; i++) {
             Py_CLEAR(f->f_localsptr[i]);
@@ -683,11 +683,10 @@ frame_tp_clear(PyFrameObject *f)
     f->f_state = FRAME_CLEARED;
 
     Py_CLEAR(f->f_trace);
-
+    PyCodeObject *co = f->f_code;
     /* locals */
-    PyObject **localsplus = f->f_localsptr;
-    for (Py_ssize_t i = frame_nslots(f); --i >= 0; ++localsplus) {
-        Py_CLEAR(*localsplus);
+    for (int i = 0; i < co->co_nlocalsplus; i++) {
+        Py_CLEAR(f->f_localsptr[i]);
     }
 
     /* stack */



More information about the Python-checkins mailing list