From 585c95df95780c3a66db8b458713b172d7874b64 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Mon, 3 Oct 2022 21:03:26 -0700 Subject: [PATCH] [3.11] GH-97752: Clear the previous member of newly-created generator/coroutine frames (GH-97812) (cherry picked from commit 93fcc1f4133e177882850177c2c047d46019b812) --- Lib/test/test_generators.py | 19 +++++++++++++++++++ ...2-10-03-13-35-48.gh-issue-97752.0xTjJY.rst | 2 ++ Python/frame.c | 3 +++ 3 files changed, 24 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-10-03-13-35-48.gh-issue-97752.0xTjJY.rst diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index e5aa7da1e0d..353073dbfce 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -206,6 +206,25 @@ class GeneratorTest(unittest.TestCase): finally: gc.set_threshold(*thresholds) + def test_ag_frame_f_back(self): + async def f(): + yield + ag = f() + self.assertIsNone(ag.ag_frame.f_back) + + def test_cr_frame_f_back(self): + async def f(): + pass + cr = f() + self.assertIsNone(cr.cr_frame.f_back) + cr.close() # Suppress RuntimeWarning. + + def test_gi_frame_f_back(self): + def f(): + yield + gi = f() + self.assertIsNone(gi.gi_frame.f_back) + class ExceptionTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-10-03-13-35-48.gh-issue-97752.0xTjJY.rst b/Misc/NEWS.d/next/Core and Builtins/2022-10-03-13-35-48.gh-issue-97752.0xTjJY.rst new file mode 100644 index 00000000000..c6563507034 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-10-03-13-35-48.gh-issue-97752.0xTjJY.rst @@ -0,0 +1,2 @@ +Fix possible data corruption or crashes when accessing the ``f_back`` member +of newly-created generator or coroutine frames. diff --git a/Python/frame.c b/Python/frame.c index ef884819e31..9d5cab990c3 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -69,6 +69,9 @@ _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest) assert(src->stacktop >= src->f_code->co_nlocalsplus); Py_ssize_t size = ((char*)&src->localsplus[src->stacktop]) - (char *)src; memcpy(dest, src, size); + // Don't leave a dangling pointer to the old frame when creating generators + // and coroutines: + dest->previous = NULL; }