From ebca9fc1ba23e58d734b9ab422da6a64fa4d72e2 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 4 Dec 2001 15:54:53 +0000 Subject: PyObject_Generic{Get,Set}Attr(): ensure that the attribute name is a string object (or a Unicode that's trivially converted to ASCII). PyObject_GetAttr(): add an 'else' to the Unicode test like PyObject_SetAttr() already has. --- Objects/object.c | 92 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/Objects/object.c b/Objects/object.c index 07ca47c..5812178 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1094,8 +1094,8 @@ PyObject_GetAttr(PyObject *v, PyObject *name) if (name == NULL) return NULL; } + else #endif - if (!PyString_Check(name)) { PyErr_SetString(PyExc_TypeError, "attribute name must be string"); @@ -1207,46 +1207,73 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name) { PyTypeObject *tp = obj->ob_type; PyObject *descr; + PyObject *res = NULL; descrgetfunc f; PyObject **dictptr; +#ifdef Py_USING_UNICODE + /* The Unicode to string conversion is done here because the + existing tp_setattro slots expect a string object as name + and we wouldn't want to break those. */ + if (PyUnicode_Check(name)) { + name = PyUnicode_AsEncodedString(name, NULL, NULL); + if (name == NULL) + return NULL; + } + else +#endif + if (!PyString_Check(name)){ + PyErr_SetString(PyExc_TypeError, + "attribute name must be string"); + return NULL; + } + else + Py_INCREF(name); + if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) - return NULL; + goto done; } descr = _PyType_Lookup(tp, name); f = NULL; if (descr != NULL) { f = descr->ob_type->tp_descr_get; - if (f != NULL && PyDescr_IsData(descr)) - return f(descr, obj, (PyObject *)obj->ob_type); + if (f != NULL && PyDescr_IsData(descr)) { + res = f(descr, obj, (PyObject *)obj->ob_type); + goto done; + } } dictptr = _PyObject_GetDictPtr(obj); if (dictptr != NULL) { PyObject *dict = *dictptr; if (dict != NULL) { - PyObject *res = PyDict_GetItem(dict, name); + res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); - return res; + goto done; } } } - if (f != NULL) - return f(descr, obj, (PyObject *)obj->ob_type); + if (f != NULL) { + res = f(descr, obj, (PyObject *)obj->ob_type); + goto done; + } if (descr != NULL) { Py_INCREF(descr); - return descr; + res = descr; + goto done; } PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", tp->tp_name, PyString_AS_STRING(name)); - return NULL; + done: + Py_DECREF(name); + return res; } int @@ -1256,18 +1283,40 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value) PyObject *descr; descrsetfunc f; PyObject **dictptr; + int res = -1; + +#ifdef Py_USING_UNICODE + /* The Unicode to string conversion is done here because the + existing tp_setattro slots expect a string object as name + and we wouldn't want to break those. */ + if (PyUnicode_Check(name)) { + name = PyUnicode_AsEncodedString(name, NULL, NULL); + if (name == NULL) + return -1; + } + else +#endif + if (!PyString_Check(name)){ + PyErr_SetString(PyExc_TypeError, + "attribute name must be string"); + return -1; + } + else + Py_INCREF(name); if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) - return -1; + goto done; } descr = _PyType_Lookup(tp, name); f = NULL; if (descr != NULL) { f = descr->ob_type->tp_descr_set; - if (f != NULL && PyDescr_IsData(descr)) - return f(descr, obj, value); + if (f != NULL && PyDescr_IsData(descr)) { + res = f(descr, obj, value); + goto done; + } } dictptr = _PyObject_GetDictPtr(obj); @@ -1276,35 +1325,38 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value) if (dict == NULL && value != NULL) { dict = PyDict_New(); if (dict == NULL) - return -1; + goto done; *dictptr = dict; } if (dict != NULL) { - int res; if (value == NULL) res = PyDict_DelItem(dict, name); else res = PyDict_SetItem(dict, name, value); if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) PyErr_SetObject(PyExc_AttributeError, name); - return res; + goto done; } } - if (f != NULL) - return f(descr, obj, value); + if (f != NULL) { + res = f(descr, obj, value); + goto done; + } if (descr == NULL) { PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", tp->tp_name, PyString_AS_STRING(name)); - return -1; + goto done; } PyErr_Format(PyExc_AttributeError, "'%.50s' object attribute '%.400s' is read-only", tp->tp_name, PyString_AS_STRING(name)); - return -1; + done: + Py_DECREF(name); + return res; } /* Test a value used as condition, e.g., in a for or if statement. -- cgit v0.12