Skip to content

Commit a05cde2

Browse files
committed
Address Guido's and Yury's reviews.
1 parent 640c799 commit a05cde2

File tree

2 files changed

+23
-21
lines changed

2 files changed

+23
-21
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
Mitigate interpreter's crashes and state corruption due to side-effects in
2-
:meth:`asyncio.Future.remove_done_callback` or others callback scheduling
1+
Mitigate interpreter crashes and state corruption due to side-effects in
2+
:meth:`asyncio.Future.remove_done_callback` or other callback scheduling
33
methods. Patch by Bénédikt Tran.

Modules/_asynciomodule.c

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,8 @@ future_schedule_callbacks(asyncio_state *state, FutureObj *fut)
434434
return 0;
435435
}
436436

437-
if (!PyList_Check(fut->fut_callbacks)) {
438-
PyErr_SetString(PyExc_RuntimeError, "corrupted future state");
437+
if (!PyList_CheckExact(fut->fut_callbacks)) {
438+
PyErr_SetString(PyExc_RuntimeError, "corrupted callbacks list");
439439
return -1;
440440
}
441441

@@ -446,19 +446,19 @@ future_schedule_callbacks(asyncio_state *state, FutureObj *fut)
446446
return 0;
447447
}
448448

449-
// Beware: 'call_soon' below may change fut_callbacks or its items
449+
// Beware: An evil 'call_soon' could change fut_callbacks or its items
450450
// (see https://github.com/python/cpython/issues/125789 for details).
451451
for (i = 0; fut->fut_callbacks != NULL; i++) {
452-
if (!PyList_Check(fut->fut_callbacks)) {
453-
PyErr_SetString(PyExc_RuntimeError, "corrupted future state");
452+
if (!PyList_CheckExact(fut->fut_callbacks)) {
453+
PyErr_SetString(PyExc_RuntimeError, "corrupted callbacks list");
454454
return -1;
455455
}
456456
if (i >= PyList_GET_SIZE(fut->fut_callbacks)) {
457457
break; // done
458458
}
459459
PyObject *cb_tup = PyList_GET_ITEM(fut->fut_callbacks, i);
460-
if (!PyTuple_Check(cb_tup) || PyTuple_GET_SIZE(cb_tup) < 2) {
461-
PyErr_SetString(PyExc_RuntimeError, "corrupted future state");
460+
if (!PyTuple_CheckExact(cb_tup) || PyTuple_GET_SIZE(cb_tup) < 2) {
461+
PyErr_SetString(PyExc_RuntimeError, "corrupted callback tuple");
462462
return -1;
463463
}
464464
PyObject *cb = PyTuple_GET_ITEM(cb_tup, 0);
@@ -1035,6 +1035,8 @@ _asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls,
10351035
ENSURE_FUTURE_ALIVE(state, self)
10361036

10371037
if (self->fut_callback0 != NULL) {
1038+
// Beware: An evil PyObject_RichCompareBool could change fut_callback0
1039+
// (see https://github.com/python/cpython/issues/125789 for details).
10381040
int cmp = PyObject_RichCompareBool(self->fut_callback0, fn, Py_EQ);
10391041
if (cmp == -1) {
10401042
return NULL;
@@ -1051,8 +1053,8 @@ _asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls,
10511053
return PyLong_FromSsize_t(cleared_callback0);
10521054
}
10531055

1054-
if (!PyList_Check(self->fut_callbacks)) {
1055-
PyErr_SetString(PyExc_RuntimeError, "corrupted future state");
1056+
if (!PyList_CheckExact(self->fut_callbacks)) {
1057+
PyErr_SetString(PyExc_RuntimeError, "corrupted callbacks list");
10561058
return NULL;
10571059
}
10581060

@@ -1064,11 +1066,11 @@ _asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls,
10641066

10651067
if (len == 1) {
10661068
PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, 0);
1067-
// Beware: PyObject_RichCompareBool below may change fut_callbacks or
1068-
// its items (see https://github.com/python/cpython/issues/97592 and
1069+
// Beware: An evil PyObject_RichCompareBool could change fut_callbacks
1070+
// or its items (see https://github.com/python/cpython/issues/97592 or
10691071
// https://github.com/python/cpython/issues/125789 for details).
1070-
if (!PyTuple_Check(cb_tup) || PyTuple_GET_SIZE(cb_tup) < 1) {
1071-
PyErr_SetString(PyExc_RuntimeError, "corrupted future state");
1072+
if (!PyTuple_CheckExact(cb_tup) || PyTuple_GET_SIZE(cb_tup) < 1) {
1073+
PyErr_SetString(PyExc_RuntimeError, "corrupted callback tuple");
10721074
return NULL;
10731075
}
10741076
Py_INCREF(cb_tup);
@@ -1092,20 +1094,20 @@ _asyncio_Future_remove_done_callback_impl(FutureObj *self, PyTypeObject *cls,
10921094
return NULL;
10931095
}
10941096

1095-
// Beware: PyObject_RichCompareBool below may change fut_callbacks or
1096-
// its items (see https://github.com/python/cpython/issues/97592 and
1097+
// Beware: An evil PyObject_RichCompareBool could change fut_callbacks
1098+
// or its items (see https://github.com/python/cpython/issues/97592 or
10971099
// https://github.com/python/cpython/issues/125789 for details).
10981100
for (i = 0; self->fut_callbacks != NULL; i++) {
1099-
if (!PyList_Check(self->fut_callbacks)) {
1100-
PyErr_SetString(PyExc_RuntimeError, "corrupted future state");
1101+
if (!PyList_CheckExact(self->fut_callbacks)) {
1102+
PyErr_SetString(PyExc_RuntimeError, "corrupted callbacks list");
11011103
goto fail;
11021104
}
11031105
if (i >= PyList_GET_SIZE(self->fut_callbacks)) {
11041106
break; // done
11051107
}
11061108
PyObject *cb_tup = PyList_GET_ITEM(self->fut_callbacks, i);
1107-
if (!PyTuple_Check(cb_tup) || PyTuple_GET_SIZE(cb_tup) < 1) {
1108-
PyErr_SetString(PyExc_RuntimeError, "corrupted future state");
1109+
if (!PyTuple_CheckExact(cb_tup) || PyTuple_GET_SIZE(cb_tup) < 1) {
1110+
PyErr_SetString(PyExc_RuntimeError, "corrupted callback tuple");
11091111
goto fail;
11101112
}
11111113
Py_INCREF(cb_tup);

0 commit comments

Comments
 (0)