diff options
author | Mark Shannon <mark@hotpy.org> | 2021-06-17 16:29:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-17 16:29:15 +0100 |
commit | ba2f32a983a08c4f64c23c187432e38908639c12 (patch) | |
tree | 763162a1c78421ea2909d142c73595613f6eba50 | |
parent | 00710e6346fd2394aa020b2dfae170093effac98 (diff) | |
download | cpython-git-ba2f32a983a08c4f64c23c187432e38908639c12.tar.gz |
Do not clear globals or builtins when calling clear() on a frame object. Reverts behavior to that of 3.10 and earlier. (GH-26768)
-rw-r--r-- | Lib/test/test_frame.py | 13 | ||||
-rw-r--r-- | Objects/frameobject.c | 9 |
2 files changed, 17 insertions, 5 deletions
diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py index 7ac37b6937..a715e725a7 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -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(): diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 99afe06d81..5057313870 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 */ |