`NULL` pointer dereference in `FutureIter_am_send`
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 77.2k
- Fork
- 35.9k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
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)]
Linked PRs
- gh-146304
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu trong Modules/_asynciomodule.c tại FutureIter_am_send và xem xét các đường đi throw() và close() hiện có được mô tả trong báo cáo. Tái hiện MRE trên CPython main, sau đó bổ sung coverage cho việc gửi sau khi iterator được xóa và xác nhận rằng nó kết thúc bằng StopIteration thay vì bị crash.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- c, python
- Lĩnh vực
- backend
- Loại issue
- Lỗi
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 35/100