]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-122695: Fix double-free when using `gc.get_referents` with a freed `_asynci...
authorVictor Stinner <vstinner@python.org>
Fri, 9 Aug 2024 14:33:24 +0000 (16:33 +0200)
committerGitHub <noreply@github.com>
Fri, 9 Aug 2024 14:33:24 +0000 (14:33 +0000)
[3.13] gh-122695: Fix double-free when using `gc.get_referents` with a freed `_asyncio.FutureIter` (#122837)

* Backport #122834 for 3.13

(cherry picked from commit e8fb088dbaa71dd5f0146b2f4a8f7ecbe2ce9625)

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
Lib/test/test_asyncio/test_futures.py
Misc/NEWS.d/next/Library/2024-08-08-15-05-58.gh-issue-122695.f7pwBv.rst [new file with mode: 0644]
Modules/_asynciomodule.c

index 2184b2091f84eed567e81502178ab1a4d143178a..6fd7436450adf753900ef0b41048495472e4cdc4 100644 (file)
@@ -641,6 +641,14 @@ class CFutureTests(BaseFutureTests, test_utils.TestCase):
         with self.assertRaises(AttributeError):
             del fut._log_traceback
 
+    def test_future_iter_get_referents_segfault(self):
+        # See https://github.com/python/cpython/issues/122695
+        import _asyncio
+        it = iter(self._new_future(loop=self.loop))
+        del it
+        evil = gc.get_referents(_asyncio)
+        gc.collect()
+
 
 @unittest.skipUnless(hasattr(futures, '_CFuture'),
                      'requires the C _asyncio module')
diff --git a/Misc/NEWS.d/next/Library/2024-08-08-15-05-58.gh-issue-122695.f7pwBv.rst b/Misc/NEWS.d/next/Library/2024-08-08-15-05-58.gh-issue-122695.f7pwBv.rst
new file mode 100644 (file)
index 0000000..cc6bc38
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed double-free when using :func:`gc.get_referents` with a freed
+:class:`asyncio.Future` iterator.
index 6b969edca2980468f537f6dfb1f88df4732d730b..1bf6b6e31c42a8e6ba7a81392618630fbfb666d3 100644 (file)
@@ -3606,14 +3606,6 @@ module_traverse(PyObject *mod, visitproc visit, void *arg)
     Py_VISIT(state->iscoroutine_typecache);
 
     Py_VISIT(state->context_kwname);
-
-    // Visit freelist.
-    PyObject *next = (PyObject*) state->fi_freelist;
-    while (next != NULL) {
-        PyObject *current = next;
-        Py_VISIT(current);
-        next = (PyObject*) ((futureiterobject*) current)->future;
-    }
     return 0;
 }