From: Guido van Rossum Date: Fri, 25 Apr 2003 05:40:32 +0000 (+0000) Subject: Backport the Carlo Verre fix. X-Git-Tag: v2.2.3c1~56 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4f017eb311454044f187d2e2930885c4da3d1eec;p=thirdparty%2FPython%2Fcpython.git Backport the Carlo Verre fix. --- diff --git a/Misc/NEWS b/Misc/NEWS index ed690b5cb0fd..e1ec2511916e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,9 @@ What's New in Python 2.2.3 ? Release date: XX-XXX-2003 ============================ +- It is no longer possible to use object.__setattr__ to circumvent the + restrictions on setting attributes of type objects. + - Implemented os.fsync() for Windows, where it calls the MS _commit() function. Before, there was no way in core Python to ensure file writes actually showed up on disk when necessary. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index b674c337783c..e4b4c5c2d748 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2594,6 +2594,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 Carlo Verre 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) { @@ -2603,6 +2621,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; @@ -2619,6 +2639,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;