-
-
Notifications
You must be signed in to change notification settings - Fork 34.2k
Description
Crash report
What happened?
It's possible to segfault the interpreter by running the MRE below.
Automated diagnosis:
Bug: NULL pointer dereference in FutureIter_am_send (_asynciomodule.c:1877). FutureIter_am_send passes it->future to Py_BEGIN_CRITICAL_SECTION() without checking for NULL. FutureIter_throw (line 1973) and FutureIter_close (line 1997) both call Py_CLEAR(self->future), setting it->future = NULL. After throw() or close(), any subsequent send()/next() dereferences NULL.
Fix: Add NULL check at the top of FutureIter_am_send:
if (it->future == NULL) {
PyErr_SetNone(PyExc_StopIteration);
*result = NULL;
return PYGEN_RETURN;
}MRE:
import asyncio
async def exploit():
loop = asyncio.get_event_loop()
fut = loop.create_future()
it = fut.__await__()
it.__next__() # yields the future, sets fut_blocking
try:
it.throw(RuntimeError) # Py_CLEAR(self->future) -> NULL
except RuntimeError:
pass
it.send(None) # SEGFAULT: Py_BEGIN_CRITICAL_SECTION(NULL)
asyncio.run(exploit())Backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x00005555560eb282 in FutureIter_am_send_lock_held (it=0x7c5ff71cf700, result=<optimized out>) at ./Modules/_asynciomodule.c:1849
1849 if (fut->fut_state == STATE_PENDING) {
(gdb) bt
#0 0x00005555560eb282 in FutureIter_am_send_lock_held (it=0x7c5ff71cf700, result=<optimized out>) at ./Modules/_asynciomodule.c:1849
#1 FutureIter_am_send (op=0x7c5ff71cf700, _unused_arg=<optimized out>, result=<optimized out>) at ./Modules/_asynciomodule.c:1878
#2 FutureIter_iternext (it=0x7c5ff71cf700) at ./Modules/_asynciomodule.c:1888
#3 0x0000555555ae6c75 in method_vectorcall_O (func=func@entry=0x7c7ff7322040, args=args@entry=0x7bfff5d36b28, nargsf=nargsf@entry=9223372036854775810, kwnames=kwnames@entry=0x0)
at Objects/descrobject.c:476
#4 0x0000555555ab9e00 in _PyObject_VectorcallTstate (tstate=0x5555568f7b18 <_PyRuntime+360664>, callable=0x7c7ff7322040, args=0x7bfff5d36b28, nargsf=9223372036854775810, kwnames=0x0)
at ./Include/internal/pycore_call.h:136
#5 0x0000555555e588dd in _Py_VectorCallInstrumentation_StackRefSteal (callable=..., arguments=<optimized out>, total_args=2, kwnames=..., call_instrumentation=<optimized out>,
frame=<optimized out>, this_instr=<optimized out>, tstate=<optimized out>) at Python/ceval.c:770
#6 0x0000555555e94263 in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized out>) at Python/generated_cases.c.h:1838
#7 0x0000555555b1f1bb in _PyEval_EvalFrame (tstate=0x5555568f7b18 <_PyRuntime+360664>, frame=0x7d0ff724c828, throwflag=0) at ./Include/internal/pycore_ceval.h:118
#8 gen_send_ex2 (gen=0x7d0ff724c7e0, arg=0x5555566bcfa0 <_Py_NoneStruct>, presult=0x7bfff5d36380, exc=0) at Objects/genobject.c:280
#9 0x0000555555a6cefc in PyIter_Send (iter=<optimized out>, arg=0x5555566bcfa0 <_Py_NoneStruct>, result=<optimized out>) at Objects/abstract.c:2936
#10 0x00005555560e584a in task_step_impl (state=<optimized out>, task=0x7d4ff704b3b0, exc=0x0) at ./Modules/_asynciomodule.c:3100
#11 0x00005555560e5033 in task_step (state=state@entry=0x7cfff7122d50, task=0x7d4ff704b3b0, exc=0x0) at ./Modules/_asynciomodule.c:3442
#12 0x00005555560e4977 in TaskStepMethWrapper_call (op=0x7c6ff76084d0, args=0x5555568c0b50 <_PyRuntime+135440>, kwds=0x0) at ./Modules/_asynciomodule.c:2112
#13 0x0000555555aba90b in _PyObject_MakeTpCall (tstate=tstate@entry=0x5555568f7b18 <_PyRuntime+360664>, callable=callable@entry=0x7c6ff76084d0, args=0x7c6ff70b2c38, nargs=0,
keywords=keywords@entry=0x0) at Objects/call.c:242
#14 0x0000555555f165c8 in _PyObject_VectorcallTstate (tstate=0x5555568f7b18 <_PyRuntime+360664>, callable=0x7c6ff76084d0, args=0x7fffffffff01, nargsf=<optimized out>, kwnames=0x0)
at ./Include/internal/pycore_call.h:134
#15 context_run (self=0x7c7ff737bec0, args=args@entry=0x7c6ff70b2c30, nargs=nargs@entry=1, kwnames=kwnames@entry=0x0) at Python/context.c:727
#16 0x0000555555bde65c in cfunction_vectorcall_FASTCALL_KEYWORDS (func=func@entry=0x7c7ff737c040, args=0x7c6ff70b2c30, nargsf=1, kwnames=kwnames@entry=0x0) at Objects/methodobject.c:465
#17 0x0000555555abc5a0 in _PyVectorcall_Call (tstate=<optimized out>, func=<optimized out>, callable=<optimized out>, tuple=0x7c6ff70b2c10, kwargs=<optimized out>) at Objects/call.c:273
#18 0x0000555555e904e2 in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized out>) at Python/generated_cases.c.h:2937
#19 0x0000555555e57778 in _PyEval_EvalFrame (tstate=0x5555568f7b18 <_PyRuntime+360664>, frame=0x7e8ff6fe5220, throwflag=0) at ./Include/internal/pycore_ceval.h:118
#20 _PyEval_Vector (tstate=<optimized out>, func=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kwnames=0x0) at Python/ceval.c:2134
#21 0x0000555555e57195 in PyEval_EvalCode (co=<optimized out>, globals=<optimized out>, locals=0x7c7ff70884c0) at Python/ceval.c:681
#22 0x0000555556061fb0 in run_eval_code_obj (tstate=tstate@entry=0x5555568f7b18 <_PyRuntime+360664>, co=co@entry=0x7d1ff701bd50, globals=globals@entry=0x7c7ff70884c0,
locals=locals@entry=0x7c7ff70884c0) at Python/pythonrun.c:1368
#23 0x000055555606117c in run_mod (mod=<optimized out>, filename=<optimized out>, globals=<optimized out>, locals=<optimized out>, flags=<optimized out>, arena=<optimized out>,
interactive_src=<optimized out>, generate_new_source=<optimized out>) at Python/pythonrun.c:1471
Found using cpython-review-toolkit with Claude Opus 4.6, using the /cpython-review-toolkit:explore Modules/_asynciomodule.c all deep command.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.15.0a7+ (heads/main:99e2c5eccd2, Mar 17 2026, 08:26:50) [Clang 21.1.2 (2ubuntu6)]
Metadata
Metadata
Assignees
Labels
Projects
Status