@@ -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