summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-04-13-18-59-25.gh-issue-115874.c3xG-E.rst1
-rw-r--r--Modules/_asynciomodule.c18
2 files changed, 17 insertions, 2 deletions
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
index 0000000..5a6fa4c
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-13-18-59-25.gh-issue-115874.c3xG-E.rst
@@ -0,0 +1 @@
+Fixed a possible segfault during garbage collection of ``_asyncio.FutureIter`` objects
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index b886051..0873d32 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -1601,11 +1601,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;