mirror of
https://github.com/python/cpython.git
synced 2026-01-06 23:42:34 +00:00
gh-125984: fix use-after-free on fut->fut_{callback,context}0 due to an evil loop.__getattribute__ (#126003)
This commit is contained in:
parent
80eec52fc8
commit
f819d4301d
3 changed files with 86 additions and 7 deletions
|
|
@ -409,12 +409,19 @@ future_schedule_callbacks(asyncio_state *state, FutureObj *fut)
|
|||
if (fut->fut_callback0 != NULL) {
|
||||
/* There's a 1st callback */
|
||||
|
||||
int ret = call_soon(state,
|
||||
fut->fut_loop, fut->fut_callback0,
|
||||
(PyObject *)fut, fut->fut_context0);
|
||||
// Beware: An evil call_soon could alter fut_callback0 or fut_context0.
|
||||
// Since we are anyway clearing them after the call, whether call_soon
|
||||
// succeeds or not, the idea is to transfer ownership so that external
|
||||
// code is not able to alter them during the call.
|
||||
PyObject *fut_callback0 = fut->fut_callback0;
|
||||
fut->fut_callback0 = NULL;
|
||||
PyObject *fut_context0 = fut->fut_context0;
|
||||
fut->fut_context0 = NULL;
|
||||
|
||||
Py_CLEAR(fut->fut_callback0);
|
||||
Py_CLEAR(fut->fut_context0);
|
||||
int ret = call_soon(state, fut->fut_loop, fut_callback0,
|
||||
(PyObject *)fut, fut_context0);
|
||||
Py_CLEAR(fut_callback0);
|
||||
Py_CLEAR(fut_context0);
|
||||
if (ret) {
|
||||
/* If an error occurs in pure-Python implementation,
|
||||
all callbacks are cleared. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue