[Python-Dev] Evil setattr hack (original) (raw)

Guido van Rossum guido@python.org
Mon, 14 Apr 2003 20:35:34 -0400


Someone accidentally discovered a way to set attributes of built-in types, even though the implementation tries to prevent this.

I've checked in what I believe is an adequate block for at least this particular hack. wrap_setattr(), which is called in response to .setattr(), now compares if the C function it is about to call is the same as the C function in the built-in base class closest to the object's class. This means that if B is a built-in class and P is a Python class derived from B, P.setattr can call B.setattr, but not A.setattr where A is an (also built-in) base class of B (unless B inherits A.setattr).

The following session shows that object.setattr can no longer be used to set a type's attributes:

Remind us that 'str' is an instance of 'type':

isinstance(str, type) True

'type' has a setattr method that forbids setting all attributes. Try type.setattr; nothing new here:

type.setattr(str, "foo", 42) Traceback (most recent call last): File "", line 1, in ? TypeError: can't set attributes of built-in/extension type 'str'

Remind us that 'object' is a base class of 'type':

issubclass(type, object) True

Now try object.setattr. This used to work; now it shows the new error message:

object.setattr(str, "foo", 42) Traceback (most recent call last): File "", line 1, in ? TypeError: can't apply this setattr to type object

delattr has the same restriction, or else you would be able to remove existing str methods -- not good:

object.delattr(str, "foo") Traceback (most recent call last): File "", line 1, in ? TypeError: can't apply this delattr to type object

In other (normal) circumstances object.setattr still works:

class C(object): ... pass ...
x = C() object.setattr(x, "foo", 42) object.delattr(x, "foo")

I'll backport this to Python 2.2 as well.

--Guido van Rossum (home page: http://www.python.org/~guido/)