]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Do not clear globals or builtins when calling clear() on a frame object. Reverts...
authorMark Shannon <mark@hotpy.org>
Thu, 17 Jun 2021 15:29:15 +0000 (16:29 +0100)
committerGitHub <noreply@github.com>
Thu, 17 Jun 2021 15:29:15 +0000 (16:29 +0100)
Lib/test/test_frame.py
Objects/frameobject.c

index 7ac37b6937502e94eeac275c3808c8ff274f7bdc..a715e725a7e45b17d4cbcb43ed56e421e27678c1 100644 (file)
@@ -45,6 +45,19 @@ class ClearTest(unittest.TestCase):
         # 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():
index 99afe06d81636ad56e9869b5b3f1f423f3b9428f..5057313870c60bf31cddc92307525ed042cf55d2 100644 (file)
@@ -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 */