mirror of
https://github.com/python/cpython.git
synced 2025-08-18 15:51:23 +00:00
[3.12] gh-125984: fix use-after-free on fut->fut_{callback,context}0
due to an evil loop.__getattribute__
(GH-126003) (#126044)
gh-125984: fix use-after-free on `fut->fut_{callback,context}0` due to an evil `loop.__getattribute__` (GH-126003)
(cherry picked from commit f819d4301d
)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
parent
67b270142d
commit
fdedb2618a
3 changed files with 86 additions and 7 deletions
|
@ -433,12 +433,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