Close off the "Verre Carlo hack" as discussed on python-dev.

This commit is contained in:
Guido van Rossum 2003-04-14 21:46:03 +00:00
parent 2fd02eb80f
commit 4dcdb78c6f
2 changed files with 39 additions and 0 deletions

View 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"

View 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;