changeset: 98571:c46ccfac8763 branch: 2.7 parent: 98548:69a26f0800b3 user: Benjamin Peterson date: Tue Oct 06 19:36:54 2015 -0700 files: Lib/test/test_descr.py Misc/NEWS Objects/typeobject.c description: prevent unacceptable bases from becoming bases through multiple inheritance (#24806) diff -r 69a26f0800b3 -r c46ccfac8763 Lib/test/test_descr.py --- a/Lib/test/test_descr.py Mon Oct 05 21:56:22 2015 -0700 +++ b/Lib/test/test_descr.py Tue Oct 06 19:36:54 2015 -0700 @@ -4065,6 +4065,37 @@ 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 -r 69a26f0800b3 -r c46ccfac8763 Misc/NEWS --- a/Misc/NEWS Mon Oct 05 21:56:22 2015 -0700 +++ b/Misc/NEWS Tue Oct 06 19:36:54 2015 -0700 @@ -10,6 +10,9 @@ 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 -r 69a26f0800b3 -r c46ccfac8763 Objects/typeobject.c --- a/Objects/typeobject.c Mon Oct 05 21:56:22 2015 -0700 +++ b/Objects/typeobject.c Tue Oct 06 19:36:54 2015 -0700 @@ -1724,6 +1724,12 @@ 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 @@ 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__");