From: Benjamin Peterson Date: Wed, 7 Oct 2015 02:36:54 +0000 (-0700) Subject: prevent unacceptable bases from becoming bases through multiple inheritance (#24806) X-Git-Tag: v2.7.11rc1~79 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=77d12ecaade4ef1b0719412cd85aeba81e3d4563;p=python prevent unacceptable bases from becoming bases through multiple inheritance (#24806) --- diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 0ac458f1e3..25f65c5a2c 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4065,6 +4065,37 @@ order (MRO) for bases """ else: assert 0, "best_base calculation found wanting" + def test_unsubclassable_types(self): + with self.assertRaises(TypeError): + class X(types.NoneType): + pass + with self.assertRaises(TypeError): + class X(object, types.NoneType): + pass + with self.assertRaises(TypeError): + class X(types.NoneType, object): + pass + class O(object): + pass + with self.assertRaises(TypeError): + class X(O, types.NoneType): + pass + with self.assertRaises(TypeError): + class X(types.NoneType, O): + pass + + class X(object): + pass + with self.assertRaises(TypeError): + X.__bases__ = types.NoneType, + with self.assertRaises(TypeError): + X.__bases__ = object, types.NoneType + with self.assertRaises(TypeError): + X.__bases__ = types.NoneType, object + with self.assertRaises(TypeError): + X.__bases__ = O, types.NoneType + with self.assertRaises(TypeError): + X.__bases__ = types.NoneType, O def test_mutable_bases_with_failing_mro(self): # Testing mutable bases with failing mro... diff --git a/Misc/NEWS b/Misc/NEWS index eb43f1f239..60dfbf0248 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 2.7.11? Core and Builtins ----------------- +- Issue #24806: Prevent builtin types that are not allowed to be subclassed from + being subclassed through multiple inheritance. + - Issue #24848: Fixed a number of bugs in UTF-7 decoding of misformed data. - Issue #25003: os.urandom() doesn't use getentropy() on Solaris because diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 9a221b396b..d3e5384a6d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1724,6 +1724,12 @@ best_base(PyObject *bases) if (PyType_Ready(base_i) < 0) return NULL; } + if (!PyType_HasFeature(base_i, Py_TPFLAGS_BASETYPE)) { + PyErr_Format(PyExc_TypeError, + "type '%.100s' is not an acceptable base type", + base_i->tp_name); + return NULL; + } candidate = solid_base(base_i); if (winner == NULL) { winner = candidate; @@ -2148,13 +2154,6 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) Py_DECREF(bases); return NULL; } - if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) { - PyErr_Format(PyExc_TypeError, - "type '%.100s' is not an acceptable base type", - base->tp_name); - Py_DECREF(bases); - return NULL; - } /* Check for a __slots__ sequence variable in dict, and count it */ slots = PyDict_GetItemString(dict, "__slots__");