]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] GH-115874: Fix segfault in FutureIter_dealloc (GH-118114)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 19 Apr 2024 22:53:18 +0000 (00:53 +0200)
committerGitHub <noreply@github.com>
Fri, 19 Apr 2024 22:53:18 +0000 (22:53 +0000)
GH-115874: Fix segfault in FutureIter_dealloc (GH-117741)
(cherry picked from commit d8f350309ded3130c43f0d2809dcb8ec13112320)

Co-authored-by: Savannah Ostrowski <savannahostrowski@gmail.com>
Misc/NEWS.d/next/Core and Builtins/2024-04-13-18-59-25.gh-issue-115874.c3xG-E.rst [new file with mode: 0644]
Modules/_asynciomodule.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-13-18-59-25.gh-issue-115874.c3xG-E.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-13-18-59-25.gh-issue-115874.c3xG-E.rst
new file mode 100644 (file)
index 0000000..5a6fa4c
--- /dev/null
@@ -0,0 +1 @@
+Fixed a possible segfault during garbage collection of ``_asyncio.FutureIter`` objects
index a465090bfaaa38fd71645ba9a16985cee7b27eec..05e79915ba7c282f761bc4ab70ff4f8ef1da987a 100644 (file)
@@ -1590,11 +1590,25 @@ static void
 FutureIter_dealloc(futureiterobject *it)
 {
     PyTypeObject *tp = Py_TYPE(it);
-    asyncio_state *state = get_asyncio_state_by_def((PyObject *)it);
+
+    // FutureIter is a heap type so any subclass must also be a heap type.
+    assert(_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
+
+    PyObject *module = ((PyHeapTypeObject*)tp)->ht_module;
+    asyncio_state *state = NULL;
+
     PyObject_GC_UnTrack(it);
     tp->tp_clear((PyObject *)it);
 
-    if (state->fi_freelist_len < FI_FREELIST_MAXLEN) {
+    // GH-115874: We can't use PyType_GetModuleByDef here as the type might have
+    // already been cleared, which is also why we must check if ht_module != NULL.
+    // Due to this restriction, subclasses that belong to a different module
+    // will not be able to use the free list.
+    if (module && _PyModule_GetDef(module) == &_asynciomodule) {
+        state = get_asyncio_state(module);
+    }
+
+    if (state && state->fi_freelist_len < FI_FREELIST_MAXLEN) {
         state->fi_freelist_len++;
         it->future = (FutureObj*) state->fi_freelist;
         state->fi_freelist = it;