Closed
Description
Crash report
What happened?
This bug boils down to a missing incref on the callback before calling PyObject_RichCompareBool
. Although we can't directly control the callbacks list with fut._callbacks
ever since it was made to return a copy every time, we can still modify it by removing/adding callbacks in evil __eq__
functions.
The bug is here
cpython/Modules/_asynciomodule.c
Lines 1049 to 1052 in 3032fcd
PoC
import asyncio
fut = asyncio.Future()
class ConfirmUAF:
def __eq__(self, other):
print("!!!! How did we get here !!!!")
class Base:
def __eq__(self, other):
print("in tracker eq", self, other)
return other != pad
def __del__(self):
# to see when objects are being deleted
print("deleting", self)
class Evil(Base):
def __eq__(self, other):
global _no_del
print("in evil eq", self, other)
fut.remove_done_callback(Base())
old_id = id(other)
del other
_no_del = ConfirmUAF()
new_id = id(_no_del)
# if these two are the same, you'll end up in the ConfirmUAF.__eq__ func
# if not, you'll probably just crash
print(f"{old_id = :#x} {new_id = :#x}")
return NotImplemented
pad = ...
fut.add_done_callback(pad)
fut.add_done_callback(Base())
assert fut.remove_done_callback(pad) == 1
print("starting bug")
fut.remove_done_callback(Evil())
Output
in tracker eq <__main__.Base object at 0x7f8cac015d40> Ellipsis
starting bug
in evil eq <__main__.Evil object at 0x7f8cac015ea0> <__main__.Base object at 0x7f8cac015d40>
in tracker eq <__main__.Base object at 0x7f8cac015d40> <__main__.Base object at 0x7f8cac016000>
in tracker eq <__main__.Base object at 0x7f8cac016000> Ellipsis
deleting <__main__.Base object at 0x7f8cac016000>
deleting <__main__.Base object at 0x7f8cac015d40>
old_id = 0x7f8cac015d40 new_id = 0x7f8cac015d40
!!!! How did we get here !!!!
deleting <__main__.Evil object at 0x7f8cac015ea0>
CPython versions tested on:
3.13, 3.14
Operating systems tested on:
Linux, Windows
Output from running 'python -VV' on the command line:
Python 3.14.0a1+ (heads/main:85799f1ffd, Nov 4 2024, 11:28:25) [GCC 13.2.0]
Linked PRs
Metadata
Metadata
Assignees
Labels
Projects
Status
Done