Skip to content

Commit d46f493

Browse files
Allow fixup_slot_dispatchers fails
1 parent 52617cb commit d46f493

File tree

1 file changed

+21
-14
lines changed

1 file changed

+21
-14
lines changed

Objects/typeobject.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3621,7 +3621,7 @@ static void object_dealloc(PyObject *);
36213621
static PyObject *object_new(PyTypeObject *, PyObject *, PyObject *);
36223622
static int object_init(PyObject *, PyObject *, PyObject *);
36233623
static int update_slot(PyTypeObject *, PyObject *);
3624-
static void fixup_slot_dispatchers(PyTypeObject *);
3624+
static int fixup_slot_dispatchers(PyTypeObject *);
36253625
static int type_new_set_names(PyTypeObject *);
36263626
static 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
1133611338
fixup_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

1138511392
static void

0 commit comments

Comments
 (0)