]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-124068: Fix reference leak with generators in the free-threaded build (#124069)
authorSam Gross <colesbury@gmail.com>
Sat, 14 Sep 2024 02:02:27 +0000 (22:02 -0400)
committerGitHub <noreply@github.com>
Sat, 14 Sep 2024 02:02:27 +0000 (22:02 -0400)
If the generator is already cleared, then most fields in the
generator's frame are not valid other than f_executable. The invalid
fields may contain dangling pointers and should not be used.

Python/gc_free_threading.c

index e981f87401a066cf22f9d2f8e4349c84ba53d458..c645f1b9a63806e2c08020d568e22884a428be19 100644 (file)
@@ -186,7 +186,20 @@ frame_disable_deferred_refcounting(_PyInterpreterFrame *frame)
     // Convert locals, variables, and the executable object to strong
     // references from (possibly) deferred references.
     assert(frame->stackpointer != NULL);
+    assert(frame->owner == FRAME_OWNED_BY_FRAME_OBJECT ||
+           frame->owner == FRAME_OWNED_BY_GENERATOR);
+
     frame->f_executable = PyStackRef_AsStrongReference(frame->f_executable);
+
+    if (frame->owner == FRAME_OWNED_BY_GENERATOR) {
+        PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
+        if (gen->gi_frame_state == FRAME_CLEARED) {
+            // gh-124068: if the generator is cleared, then most fields other
+            // than f_executable are not valid.
+            return;
+        }
+    }
+
     for (_PyStackRef *ref = frame->localsplus; ref < frame->stackpointer; ref++) {
         if (!PyStackRef_IsNull(*ref) && PyStackRef_IsDeferred(*ref)) {
             *ref = PyStackRef_AsStrongReference(*ref);