Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
gh-125789: fix side-effects inasyncio callback scheduling methods#125833
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Changes from1 commit
be7cac9ca61908640c799a05cde222b21ccf7b6730f72c393378fe09File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| Mitigate interpreter crashes and state corruption due to side-effects in | ||
| :meth:`asyncio.Future.remove_done_callback` orother callback scheduling | ||
| methods. Patch by Bénédikt Tran. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -434,8 +434,8 @@ future_schedule_callbacks(asyncio_state *state, FutureObj *fut) | ||
| return 0; | ||
| } | ||
| if (!PyList_CheckExact(fut->fut_callbacks)) { | ||
| ||
| PyErr_SetString(PyExc_RuntimeError, "corruptedcallbacks list"); | ||
| return -1; | ||
| } | ||
| @@ -446,19 +446,19 @@ future_schedule_callbacks(asyncio_state *state, FutureObj *fut) | ||
| return 0; | ||
| } | ||
| // Beware:An evil'call_soon'could change fut_callbacks or its items | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Do you have a test case for an evil 'call_soon'? MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. No, you're right. I didn't test but I think we can just call Contributor
| ||
| // (see https://github.com/python/cpython/issues/125789 for details). | ||
| for (i = 0; fut->fut_callbacks != NULL; i++) { | ||
| if (!PyList_CheckExact(fut->fut_callbacks)) { | ||
| PyErr_SetString(PyExc_RuntimeError, "corruptedcallbacks list"); | ||
| return -1; | ||
| } | ||
| if (i >= PyList_GET_SIZE(fut->fut_callbacks)) { | ||
| break; // done | ||
| } | ||
| PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i); | ||
| if (!PyTuple_CheckExact(cb_tup) || PyTuple_GET_SIZE(cb_tup) < 2) { | ||
| PyErr_SetString(PyExc_RuntimeError, "corruptedcallback tuple"); | ||
| return -1; | ||
| } | ||
| PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0); | ||
| @@ -1035,6 +1035,8 @@ _asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls, | ||
| ENSURE_FUTURE_ALIVE(state, self) | ||
| if (self->fut_callback0 != NULL) { | ||
| // Beware: An evil PyObject_RichCompareBool could change fut_callback0 | ||
| // (see https://github.com/python/cpython/issues/125789 for details). | ||
| int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ); | ||
| if (cmp == -1) { | ||
| return NULL; | ||
| @@ -1051,8 +1053,8 @@ _asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls, | ||
| return PyLong_FromSsize_t(cleared_callback0); | ||
| } | ||
| if (!PyList_CheckExact(self->fut_callbacks)) { | ||
| PyErr_SetString(PyExc_RuntimeError, "corruptedcallbacks list"); | ||
| return NULL; | ||
| } | ||
| @@ -1064,11 +1066,11 @@ _asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls, | ||
| if (len == 1) { | ||
| PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0); | ||
| // Beware:An evil PyObject_RichCompareBool couldchange fut_callbacks | ||
| //orits items (see https://github.com/python/cpython/issues/97592or | ||
| // https://github.com/python/cpython/issues/125789 for details). | ||
| if (!PyTuple_CheckExact(cb_tup) || PyTuple_GET_SIZE(cb_tup) < 1) { | ||
| PyErr_SetString(PyExc_RuntimeError, "corruptedcallback tuple"); | ||
| return NULL; | ||
| } | ||
| Py_INCREF(cb_tup); | ||
| @@ -1092,20 +1094,20 @@ _asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls, | ||
| return NULL; | ||
| } | ||
| // Beware:An evil PyObject_RichCompareBool couldchange fut_callbacks | ||
| //orits items (see https://github.com/python/cpython/issues/97592or | ||
| // https://github.com/python/cpython/issues/125789 for details). | ||
| for (i = 0; self->fut_callbacks != NULL; i++) { | ||
| if (!PyList_CheckExact(self->fut_callbacks)) { | ||
| PyErr_SetString(PyExc_RuntimeError, "corruptedcallbacks list"); | ||
| goto fail; | ||
| } | ||
| if (i >= PyList_GET_SIZE(self->fut_callbacks)) { | ||
| break; // done | ||
| } | ||
| PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, i); | ||
| if (!PyTuple_CheckExact(cb_tup) || PyTuple_GET_SIZE(cb_tup) < 1) { | ||
| PyErr_SetString(PyExc_RuntimeError, "corruptedcallback tuple"); | ||
| goto fail; | ||
| } | ||
| Py_INCREF(cb_tup); | ||