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:
Armin Rigo 2005-12-29 17:07:39 +00:00
parent f5bd3b442d
commit 037d1e0ff3
2 changed files with 64 additions and 0 deletions

View File

@ -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..."

View File

@ -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;
}