]> granicus.if.org Git - python/commitdiff
Close off the "Verre Carlo hack" as discussed on python-dev.
authorGuido van Rossum <guido@python.org>
Mon, 14 Apr 2003 21:46:03 +0000 (21:46 +0000)
committerGuido van Rossum <guido@python.org>
Mon, 14 Apr 2003 21:46:03 +0000 (21:46 +0000)
Lib/test/test_descr.py
Objects/typeobject.c

index 507938e607701ca69788b44612b46045da471c8a..37d8b65db64b1cb48046bfb87db0298859658a61 100644 (file)
@@ -3840,6 +3840,22 @@ def proxysuper():
     p = Proxy(obj)
     vereq(C.__dict__["f"](p), "B.f->C.f")
 
+def verrecarlo():
+    if verbose:
+        print "Testing prohibition of Verre Carlo's hack..."
+    try:
+        object.__setattr__(str, "foo", 42)
+    except TypeError:
+        pass
+    else:
+        raise TestFailed, "Verre Carlo __setattr__ suceeded!"
+    try:
+        object.__delattr__(str, "lower")
+    except TypeError:
+        pass
+    else:
+        raise TestFailed, "Verre Carlo __delattr__ succeeded!"
+
 
 def test_main():
     do_this_first()
@@ -3929,6 +3945,7 @@ def test_main():
     meth_class_get()
     isinst_isclass()
     proxysuper()
+    verrecarlo()
 
     if verbose: print "All OK"
 
index a900f55e46f015fe00f72e191580f03e668ee8eb..91c40b9999df1632da1b2352c7766fdecb102295 100644 (file)
@@ -3574,6 +3574,24 @@ wrap_cmpfunc(PyObject *self, PyObject *args, void *wrapped)
        return PyInt_FromLong((long)res);
 }
 
+/* Helper to check for object.__setattr__ or __delattr__ applied to a type.
+   This is called the Verre Carlo hack after its discoverer. */
+static int
+hackcheck(PyObject *self, setattrofunc func, char *what)
+{
+       PyTypeObject *type = self->ob_type;
+       while (type && type->tp_flags & Py_TPFLAGS_HEAPTYPE)
+               type = type->tp_base;
+       if (type->tp_setattro != func) {
+               PyErr_Format(PyExc_TypeError,
+                            "can't apply this %s to %s object",
+                            what,
+                            type->tp_name);
+               return 0;
+       }
+       return 1;
+}
+
 static PyObject *
 wrap_setattr(PyObject *self, PyObject *args, void *wrapped)
 {
@@ -3583,6 +3601,8 @@ wrap_setattr(PyObject *self, PyObject *args, void *wrapped)
 
        if (!PyArg_ParseTuple(args, "OO", &name, &value))
                return NULL;
+       if (!hackcheck(self, func, "__setattr__"))
+               return NULL;
        res = (*func)(self, name, value);
        if (res < 0)
                return NULL;
@@ -3599,6 +3619,8 @@ wrap_delattr(PyObject *self, PyObject *args, void *wrapped)
 
        if (!PyArg_ParseTuple(args, "O", &name))
                return NULL;
+       if (!hackcheck(self, func, "__delattr__"))
+               return NULL;
        res = (*func)(self, name, NULL);
        if (res < 0)
                return NULL;