Crash report
Bug description:
In future_schedule_callbacks, the length of the callback list is assumed to be constant, but an evil call_soon can make it change.
PoC:
import asyncio called_on_fut_callback0 = False pad = lambda: ... def evil_call_soon(*args, **kwargs): global called_on_fut_callback0 if called_on_fut_callback0: # Called when handling fut->fut_callbacks[0] # and mutates the length fut->fut_callbacks. fut.remove_done_callback(int) fut.remove_done_callback(pad) else: called_on_fut_callback0 = True fake_event_loop = lambda: ... fake_event_loop.call_soon = evil_call_soon fake_event_loop.get_debug = lambda: False # suppress traceback fut = asyncio.Future(loop=fake_event_loop) fut.add_done_callback(str) # sets fut->fut_callback0 fut.add_done_callback(int) # sets fut->fut_callbacks[0] fut.add_done_callback(pad) # sets fut->fut_callbacks[1] fut.add_done_callback(pad) # sets fut->fut_callbacks[2] fut.set_result("boom")
CPython versions tested on:
CPython main branch
Operating systems tested on:
No response