[Python-checkins] commit of r41845 - in python/trunk: Lib/test/test_descr.py Objects/typeobject.c

armin.rigo python-checkins at python.org
Thu Dec 29 18:07:41 CET 2005


Author: armin.rigo
Date: Thu Dec 29 18:07:39 2005
New Revision: 41845

Modified:
   python/trunk/Lib/test/test_descr.py
   python/trunk/Objects/typeobject.c
Log:
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.


Modified: python/trunk/Lib/test/test_descr.py
==============================================================================
--- python/trunk/Lib/test/test_descr.py	(original)
+++ python/trunk/Lib/test/test_descr.py	Thu Dec 29 18:07:39 2005
@@ -1635,6 +1635,37 @@
     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..."
 

Modified: python/trunk/Objects/typeobject.c
==============================================================================
--- python/trunk/Objects/typeobject.c	(original)
+++ python/trunk/Objects/typeobject.c	Thu Dec 29 18:07:39 2005
@@ -1288,12 +1288,14 @@
 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 @@
 		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;
 }


More information about the Python-checkins mailing list