Skip to content

Commit f032f6b

Browse files
gh-126138: Fix use-after-free in _asyncio.Task by evil __getattribute__ (#126305)
Co-authored-by: Carol Willing <[email protected]>
1 parent 914356f commit f032f6b

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a use-after-free crash on :class:`asyncio.Task` objects
2+
whose underlying coroutine yields an object that implements
3+
an evil :meth:`~object.__getattribute__`. Patch by Nico Posada.

Modules/_asynciomodule.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2967,8 +2967,17 @@ task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *resu
29672967
if (task->task_must_cancel) {
29682968
PyObject *r;
29692969
int is_true;
2970+
2971+
// Beware: An evil `__getattribute__` could
2972+
// prematurely delete task->task_cancel_msg before the
2973+
// task is cancelled, thereby causing a UAF crash.
2974+
//
2975+
// See https://github.com/python/cpython/issues/126138
2976+
PyObject *task_cancel_msg = Py_NewRef(task->task_cancel_msg);
29702977
r = PyObject_CallMethodOneArg(result, &_Py_ID(cancel),
2971-
task->task_cancel_msg);
2978+
task_cancel_msg);
2979+
Py_DECREF(task_cancel_msg);
2980+
29722981
if (r == NULL) {
29732982
return NULL;
29742983
}
@@ -3060,8 +3069,17 @@ task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *resu
30603069
if (task->task_must_cancel) {
30613070
PyObject *r;
30623071
int is_true;
3072+
3073+
// Beware: An evil `__getattribute__` could
3074+
// prematurely delete task->task_cancel_msg before the
3075+
// task is cancelled, thereby causing a UAF crash.
3076+
//
3077+
// See https://github.com/python/cpython/issues/126138
3078+
PyObject *task_cancel_msg = Py_NewRef(task->task_cancel_msg);
30633079
r = PyObject_CallMethodOneArg(result, &_Py_ID(cancel),
3064-
task->task_cancel_msg);
3080+
task_cancel_msg);
3081+
Py_DECREF(task_cancel_msg);
3082+
30653083
if (r == NULL) {
30663084
return NULL;
30673085
}

0 commit comments

Comments
 (0)