GH-115874: Fix segfault in FutureIter_dealloc (GH-117741)

This commit is contained in:
Savannah Ostrowski 2024-04-19 15:30:52 -07:00 committed by GitHub
parent 07525c9a85
commit d8f350309d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 17 additions and 2 deletions

View File

@ -0,0 +1 @@
Fixed a possible segfault during garbage collection of ``_asyncio.FutureIter`` objects

View File

@ -1601,11 +1601,25 @@ static void
FutureIter_dealloc(futureiterobject *it) FutureIter_dealloc(futureiterobject *it)
{ {
PyTypeObject *tp = Py_TYPE(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); PyObject_GC_UnTrack(it);
tp->tp_clear((PyObject *)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++; state->fi_freelist_len++;
it->future = (FutureObj*) state->fi_freelist; it->future = (FutureObj*) state->fi_freelist;
state->fi_freelist = it; state->fi_freelist = it;