@@ -3621,7 +3621,7 @@ static void object_dealloc(PyObject *);
36213621static PyObject * object_new (PyTypeObject * , PyObject * , PyObject * );
36223622static int object_init (PyObject * , PyObject * , PyObject * );
36233623static int update_slot (PyTypeObject * , PyObject * );
3624- static void fixup_slot_dispatchers (PyTypeObject * );
3624+ static int fixup_slot_dispatchers (PyTypeObject * );
36253625static int type_new_set_names (PyTypeObject * );
36263626static int type_new_init_subclass (PyTypeObject * , PyObject * );
36273627
@@ -4577,7 +4577,9 @@ type_new_impl(type_new_ctx *ctx)
45774577 }
45784578
45794579 // Put the proper slots in place
4580- fixup_slot_dispatchers (type );
4580+ if (fixup_slot_dispatchers (type ) < 0 ) {
4581+ goto error ;
4582+ }
45814583
45824584 if (!_PyDict_HasOnlyStringKeys (type -> tp_dict )) {
45834585 if (PyErr_WarnFormat (
@@ -11331,25 +11333,24 @@ update_slot(PyTypeObject *type, PyObject *name)
1133111333
1133211334/* Store the proper functions in the slot dispatches at class (type)
1133311335 definition time, based upon which operations the class overrides in its
11334- dict. */
11335- static void
11336+ dict. Returns -1 and exception set on error or 0 otherwise. */
11337+ static int
1133611338fixup_slot_dispatchers (PyTypeObject * type )
1133711339{
11340+ int res = 0 ;
11341+
1133811342 // This lock isn't strictly necessary because the type has not been
1133911343 // exposed to anyone else yet, but update_ont_slot calls find_name_in_mro
1134011344 // where we'd like to assert that the type is locked.
1134111345 BEGIN_TYPE_LOCK ();
1134211346
11343- PyObject * mro = lookup_tp_mro (type );
11344- assert (mro );
11347+ PyObject * mro = Py_NewRef (lookup_tp_mro (type ));
1134511348
1134611349 // Try to prebuild MRO dict. We build it in bottom-top manner,
1134711350 // from bottom base to the top one, because the bottommost base
1134811351 // has more items then other and copying it is preferable than
1134911352 // merging.
11350- // If we fails then clear mro_dict and reset error flag because
11351- // we don't expect any exceptions. If fails to prebuild MRO dict
11352- // then update_on_slot will use previous version of find_name_in_mro.
11353+ // If we fails, then stop init type.
1135311354 PyObject * mro_dict = NULL ;
1135411355 Py_ssize_t n = PyTuple_GET_SIZE (mro );
1135511356 for (Py_ssize_t i = 0 ; i < n ; i ++ ) {
@@ -11360,26 +11361,32 @@ fixup_slot_dispatchers(PyTypeObject *type)
1136011361 if (i == 0 ) {
1136111362 mro_dict = PyDict_Copy (dict );
1136211363 if (!mro_dict ) {
11363- PyErr_Clear () ;
11364- break ;
11364+ res = -1 ;
11365+ goto finish ;
1136511366 }
1136611367 } else {
1136711368 if (PyDict_Merge (mro_dict , dict , 1 ) < 0 ) {
11368- Py_CLEAR (mro_dict );
11369- PyErr_Clear ();
11370- break ;
11369+ res = -1 ;
11370+ goto finish ;
1137111371 }
1137211372 }
1137311373 }
1137411374
11375+ assert (!res );
11376+ assert (mro_dict );
1137511377 assert (!PyErr_Occurred ());
1137611378 for (pytype_slotdef * p = slotdefs ; p -> name ; ) {
1137711379 p = update_one_slot (type , p , mro_dict );
1137811380 }
1137911381
11382+ assert (!PyErr_Occurred ());
11383+
11384+ finish :
1138011385 Py_XDECREF (mro_dict );
11386+ Py_DECREF (mro );
1138111387
1138211388 END_TYPE_LOCK ();
11389+ return res ;
1138311390}
1138411391
1138511392static void
0 commit comments