Skip to content

Commit b592699

Browse files
miss-islingtonNico-Posadawillingc
authored
[3.12] gh-126138: Fix use-after-free in _asyncio.Task by evil __getattribute__ (GH-126305) (#126325)
gh-126138: Fix use-after-free in `_asyncio.Task` by evil `__getattribute__` (GH-126305) (cherry picked from commit f032f6b) Co-authored-by: Nico-Posada <[email protected]> Co-authored-by: Carol Willing <[email protected]>
1 parent 8d4ef52 commit b592699

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
@@ -2994,8 +2994,17 @@ task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *resu
29942994
if (task->task_must_cancel) {
29952995
PyObject *r;
29962996
int is_true;
2997+
2998+
// Beware: An evil `__getattribute__` could
2999+
// prematurely delete task->task_cancel_msg before the
3000+
// task is cancelled, thereby causing a UAF crash.
3001+
//
3002+
// See https://github.com/python/cpython/issues/126138
3003+
PyObject *task_cancel_msg = Py_NewRef(task->task_cancel_msg);
29973004
r = PyObject_CallMethodOneArg(result, &_Py_ID(cancel),
2998-
task->task_cancel_msg);
3005+
task_cancel_msg);
3006+
Py_DECREF(task_cancel_msg);
3007+
29993008
if (r == NULL) {
30003009
return NULL;
30013010
}
@@ -3087,8 +3096,17 @@ task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *resu
30873096
if (task->task_must_cancel) {
30883097
PyObject *r;
30893098
int is_true;
3099+
3100+
// Beware: An evil `__getattribute__` could
3101+
// prematurely delete task->task_cancel_msg before the
3102+
// task is cancelled, thereby causing a UAF crash.
3103+
//
3104+
// See https://github.com/python/cpython/issues/126138
3105+
PyObject *task_cancel_msg = Py_NewRef(task->task_cancel_msg);
30903106
r = PyObject_CallMethodOneArg(result, &_Py_ID(cancel),
3091-
task->task_cancel_msg);
3107+
task_cancel_msg);
3108+
Py_DECREF(task_cancel_msg);
3109+
30923110
if (r == NULL) {
30933111
return NULL;
30943112
}

0 commit comments

Comments
 (0)