diff options
author | Marc-André Lemburg <mal@egenix.com> | 2000-09-18 16:20:57 (GMT) |
---|---|---|
committer | Marc-André Lemburg <mal@egenix.com> | 2000-09-18 16:20:57 (GMT) |
commit | e44e507b0e60de842f57ca79b45696dd263f257f (patch) | |
tree | 7c2c0714e7bfa7231350b099e5bf8b1a0e0367d9 /Objects | |
parent | 1de8098ca685a2d9e9c5eb2e3ebaeb8190004b4c (diff) | |
download | cpython-e44e507b0e60de842f57ca79b45696dd263f257f.zip cpython-e44e507b0e60de842f57ca79b45696dd263f257f.tar.gz cpython-e44e507b0e60de842f57ca79b45696dd263f257f.tar.bz2 |
PyObject_SetAttr() and PyObject_GetAttr() now also accept Unicode
objects for the attribute name. Unicode objects are converted to
a string using the default encoding before trying the lookup.
Note that previously it was allowed to pass arbitrary objects as
attribute name in case the tp_getattro/setattro slots were defined.
This patch fixes this by applying an explicit string check first:
all uses of these slots expect string objects and do not check
for the type resulting in a core dump. The tp_getattro/setattro
are still useful as optimization for lookups using interned
string objects though.
This patch fixes bug #113829.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/object.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/Objects/object.c b/Objects/object.c index 150f357..3323906 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -703,17 +703,31 @@ PyObject_SetAttrString(PyObject *v, char *name, PyObject *w) } } +/* Internal API needed by PyObject_GetAttr(): */ +extern +PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode, + const char *errors); + PyObject * PyObject_GetAttr(PyObject *v, PyObject *name) { - if (v->ob_type->tp_getattro != NULL) - return (*v->ob_type->tp_getattro)(v, name); + /* The Unicode to string conversion is done here because the + existing tp_getattro slots expect a string object as name + and we wouldn't want to break those. */ + if (PyUnicode_Check(name)) { + name = _PyUnicode_AsDefaultEncodedString(name, NULL); + if (name == NULL) + return NULL; + } if (!PyString_Check(name)) { PyErr_SetString(PyExc_TypeError, "attribute name must be string"); return NULL; } + if (v->ob_type->tp_getattro != NULL) + return (*v->ob_type->tp_getattro)(v, name); + else return PyObject_GetAttrString(v, PyString_AS_STRING(name)); } @@ -733,20 +747,32 @@ int PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value) { int err; - Py_INCREF(name); - if (PyString_Check(name)) - PyString_InternInPlace(&name); - if (v->ob_type->tp_setattro != NULL) - err = (*v->ob_type->tp_setattro)(v, name, value); - else if (PyString_Check(name)) { - err = PyObject_SetAttrString( - v, PyString_AS_STRING(name), value); + + /* 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 { + else + Py_INCREF(name); + + if (!PyString_Check(name)){ PyErr_SetString(PyExc_TypeError, "attribute name must be string"); err = -1; } + else { + PyString_InternInPlace(&name); + if (v->ob_type->tp_setattro != NULL) + err = (*v->ob_type->tp_setattro)(v, name, value); + else + err = PyObject_SetAttrString(v, + PyString_AS_STRING(name), value); + } + Py_DECREF(name); return err; } |