Disallow class assignment completely unless both old and new are heap

types.  This prevents nonsense like 2.__class__ = bool or
True.__class__ = int.
This commit is contained in:
Guido van Rossum 2002-08-10 05:42:07 +00:00
parent e05f65a0c6
commit 40af889081
2 changed files with 14 additions and 6 deletions

View file

@ -2478,6 +2478,11 @@ def setclass():
cant(C(), object) cant(C(), object)
cant(object(), list) cant(object(), list)
cant(list(), object) cant(list(), object)
class Int(int): __slots__ = []
cant(2, Int)
cant(Int(), int)
cant(True, int)
cant(2, bool)
def setdict(): def setdict():
if verbose: print "Testing __dict__ assignment..." if verbose: print "Testing __dict__ assignment..."

View file

@ -1745,6 +1745,13 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
return -1; return -1;
} }
new = (PyTypeObject *)value; new = (PyTypeObject *)value;
if (!(new->tp_flags & Py_TPFLAGS_HEAPTYPE) ||
!(old->tp_flags & Py_TPFLAGS_HEAPTYPE))
{
PyErr_Format(PyExc_TypeError,
"__class__ assignment: only for heap types");
return -1;
}
if (new->tp_dealloc != old->tp_dealloc || if (new->tp_dealloc != old->tp_dealloc ||
new->tp_free != old->tp_free) new->tp_free != old->tp_free)
{ {
@ -1771,13 +1778,9 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
old->tp_name); old->tp_name);
return -1; return -1;
} }
if (new->tp_flags & Py_TPFLAGS_HEAPTYPE) { Py_INCREF(new);
Py_INCREF(new);
}
self->ob_type = new; self->ob_type = new;
if (old->tp_flags & Py_TPFLAGS_HEAPTYPE) { Py_DECREF(old);
Py_DECREF(old);
}
return 0; return 0;
} }