SF bug #1153075: "PyXxx_Check(x) trusts x->ob_type->tp_mro".
A patch by mwh to check that user-defined mro's are reasonable enough.
This commit is contained in:
parent
f5bd3b442d
commit
037d1e0ff3
|
@ -1635,6 +1635,37 @@ def altmro():
|
|||
vereq(X.__mro__, (object, A, C, B, D, X))
|
||||
vereq(X().f(), "A")
|
||||
|
||||
try:
|
||||
class X(object):
|
||||
class __metaclass__(type):
|
||||
def mro(self):
|
||||
return [self, dict, object]
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed, "devious mro() return not caught"
|
||||
|
||||
try:
|
||||
class X(object):
|
||||
class __metaclass__(type):
|
||||
def mro(self):
|
||||
return [1]
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed, "non-class mro() return not caught"
|
||||
|
||||
try:
|
||||
class X(object):
|
||||
class __metaclass__(type):
|
||||
def mro(self):
|
||||
return 1
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed, "non-sequence mro() return not caught"
|
||||
|
||||
|
||||
def overloading():
|
||||
if verbose: print "Testing operator overloading..."
|
||||
|
||||
|
|
|
@ -1288,12 +1288,14 @@ static int
|
|||
mro_internal(PyTypeObject *type)
|
||||
{
|
||||
PyObject *mro, *result, *tuple;
|
||||
int checkit = 0;
|
||||
|
||||
if (type->ob_type == &PyType_Type) {
|
||||
result = mro_implementation(type);
|
||||
}
|
||||
else {
|
||||
static PyObject *mro_str;
|
||||
checkit = 1;
|
||||
mro = lookup_method((PyObject *)type, "mro", &mro_str);
|
||||
if (mro == NULL)
|
||||
return -1;
|
||||
|
@ -1304,6 +1306,37 @@ mro_internal(PyTypeObject *type)
|
|||
return -1;
|
||||
tuple = PySequence_Tuple(result);
|
||||
Py_DECREF(result);
|
||||
if (tuple == NULL)
|
||||
return -1;
|
||||
if (checkit) {
|
||||
int i, len;
|
||||
PyObject *cls;
|
||||
PyTypeObject *solid;
|
||||
|
||||
solid = solid_base(type);
|
||||
|
||||
len = PyTuple_GET_SIZE(tuple);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
PyTypeObject *t;
|
||||
cls = PyTuple_GET_ITEM(tuple, i);
|
||||
if (PyClass_Check(cls))
|
||||
continue;
|
||||
else if (!PyType_Check(cls)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"mro() returned a non-class ('%.500s')",
|
||||
cls->ob_type->tp_name);
|
||||
return -1;
|
||||
}
|
||||
t = (PyTypeObject*)cls;
|
||||
if (!PyType_IsSubtype(solid, solid_base(t))) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"mro() returned base with unsuitable layout ('%.500s')",
|
||||
t->tp_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
type->tp_mro = tuple;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue