From 4dcdb78c6ffd203c9d72ef41638cc4a0e3857adf Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 14 Apr 2003 21:46:03 +0000 Subject: Close off the "Verre Carlo hack" as discussed on python-dev. --- Lib/test/test_descr.py | 17 +++++++++++++++++ Objects/typeobject.c | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 507938e..37d8b65 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -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" diff --git a/Objects/typeobject.c b/Objects/typeobject.c index a900f55..91c40b9 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -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; -- cgit v0.12