8000 [3.10] gh-92112: Fix crash triggered by an evil custom `mro()` (GH-92… · python/cpython@4674b31 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4674b31

Browse files
JelleZijlstraAlexey Izbyshev
andauthored
[3.10] gh-92112: Fix crash triggered by an evil custom mro() (GH-92113) (#92370)
(cherry picked from commit 85354ed) Co-authored-by: Alexey Izbyshev <izbyshev@ispras.ru>
1 parent 17f3b5c commit 4674b31

File tree

3 files changed

+29
-9
lines changed

3 files changed

+29
-9
lines changed

Lib/test/test_descr.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5737,6 +5737,23 @@ def mro(cls):
57375737
class A(metaclass=M):
57385738
pass
57395739

5740+
def test_disappearing_custom_mro(self):
5741+
"""
5742+
gh-92112: A custom mro() returning a result conflicting with
5743+
__bases__ and deleting itself caused a double free.
5744+
"""
5745+
class B:
5746+
pass
5747+
5748+
class M(DebugHelperMeta):
5749+
def mro(cls):
5750+
del M.mro
5751+
return (B,)
5752+
5753+
with self.assertRaises(TypeError):
5754+
class A(metaclass=M):
5755+
pass
5756+
57405757

57415758
if __name__ == "__main__":
57425759
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix crash triggered by an evil custom ``mro()`` on a metaclass.

Objects/typeobject.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -369,22 +369,26 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
369369
Py_ssize_t i, n;
370370
int custom = !Py_IS_TYPE(type, &PyType_Type);
371371
int unbound;
372-
PyObject *mro_meth = NULL;
373-
PyObject *type_mro_meth = NULL;
374372

375373
if (custom) {
374+
PyObject *mro_meth, *type_mro_meth;
376375
mro_meth = lookup_maybe_method(
377376
(PyObject *)type, &PyId_mro, &unbound);
378-
if (mro_meth == NULL)
377+
if (mro_meth == NULL) {
379378
goto clear;
379+
}
380380
type_mro_meth = lookup_maybe_method(
381381
(PyObject *)&PyType_Type, &PyId_mro, &unbound);
382-
if (type_mro_meth == NULL)
382+
if (type_mro_meth == NULL) {
383+
Py_DECREF(mro_meth);
383384
goto clear;
384-
if (mro_meth != type_mro_meth)
385+
}
386+
int custom_mro = (mro_meth != type_mro_meth);
387+
Py_DECREF(mro_meth);
388+
Py_DECREF(type_mro_meth);
389+
if (custom_mro) {
385390
goto clear;
386-
Py_XDECREF(mro_meth);
387-
Py_XDECREF(type_mro_meth);
391+
}
388392
}
389393
n = PyTuple_GET_SIZE(bases);
390394
for (i = 0; i < n; i++) {
@@ -400,8 +404,6 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
400404
}
401405
return;
402406
clear:
403-
Py_XDECREF(mro_meth);
404-
Py_XDECREF(type_mro_meth);
405407
type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
406408
type->tp_version_tag = 0; /* 0 is not a valid version tag */
407409
}

0 commit comments

Comments
 (0)
0