mirror of
https://github.com/python/cpython.git
synced 2025-08-22 17:55:18 +00:00
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.
This commit is contained in:
parent
d3d8a1df5c
commit
ebca9fc1ba
1 changed files with 72 additions and 20 deletions
|
@ -1094,8 +1094,8 @@ PyObject_GetAttr(PyObject *v, PyObject *name)
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!PyString_Check(name)) {
|
if (!PyString_Check(name)) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"attribute name must be string");
|
"attribute name must be string");
|
||||||
|
@ -1207,46 +1207,73 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
|
||||||
{
|
{
|
||||||
PyTypeObject *tp = obj->ob_type;
|
PyTypeObject *tp = obj->ob_type;
|
||||||
PyObject *descr;
|
PyObject *descr;
|
||||||
|
PyObject *res = NULL;
|
||||||
descrgetfunc f;
|
descrgetfunc f;
|
||||||
PyObject **dictptr;
|
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 (tp->tp_dict == NULL) {
|
||||||
if (PyType_Ready(tp) < 0)
|
if (PyType_Ready(tp) < 0)
|
||||||
return NULL;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
descr = _PyType_Lookup(tp, name);
|
descr = _PyType_Lookup(tp, name);
|
||||||
f = NULL;
|
f = NULL;
|
||||||
if (descr != NULL) {
|
if (descr != NULL) {
|
||||||
f = descr->ob_type->tp_descr_get;
|
f = descr->ob_type->tp_descr_get;
|
||||||
if (f != NULL && PyDescr_IsData(descr))
|
if (f != NULL && PyDescr_IsData(descr)) {
|
||||||
return f(descr, obj, (PyObject *)obj->ob_type);
|
res = f(descr, obj, (PyObject *)obj->ob_type);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dictptr = _PyObject_GetDictPtr(obj);
|
dictptr = _PyObject_GetDictPtr(obj);
|
||||||
if (dictptr != NULL) {
|
if (dictptr != NULL) {
|
||||||
PyObject *dict = *dictptr;
|
PyObject *dict = *dictptr;
|
||||||
if (dict != NULL) {
|
if (dict != NULL) {
|
||||||
PyObject *res = PyDict_GetItem(dict, name);
|
res = PyDict_GetItem(dict, name);
|
||||||
if (res != NULL) {
|
if (res != NULL) {
|
||||||
Py_INCREF(res);
|
Py_INCREF(res);
|
||||||
return res;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f != NULL)
|
if (f != NULL) {
|
||||||
return f(descr, obj, (PyObject *)obj->ob_type);
|
res = f(descr, obj, (PyObject *)obj->ob_type);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (descr != NULL) {
|
if (descr != NULL) {
|
||||||
Py_INCREF(descr);
|
Py_INCREF(descr);
|
||||||
return descr;
|
res = descr;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyErr_Format(PyExc_AttributeError,
|
PyErr_Format(PyExc_AttributeError,
|
||||||
"'%.50s' object has no attribute '%.400s'",
|
"'%.50s' object has no attribute '%.400s'",
|
||||||
tp->tp_name, PyString_AS_STRING(name));
|
tp->tp_name, PyString_AS_STRING(name));
|
||||||
return NULL;
|
done:
|
||||||
|
Py_DECREF(name);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1256,18 +1283,40 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
|
||||||
PyObject *descr;
|
PyObject *descr;
|
||||||
descrsetfunc f;
|
descrsetfunc f;
|
||||||
PyObject **dictptr;
|
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 (tp->tp_dict == NULL) {
|
||||||
if (PyType_Ready(tp) < 0)
|
if (PyType_Ready(tp) < 0)
|
||||||
return -1;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
descr = _PyType_Lookup(tp, name);
|
descr = _PyType_Lookup(tp, name);
|
||||||
f = NULL;
|
f = NULL;
|
||||||
if (descr != NULL) {
|
if (descr != NULL) {
|
||||||
f = descr->ob_type->tp_descr_set;
|
f = descr->ob_type->tp_descr_set;
|
||||||
if (f != NULL && PyDescr_IsData(descr))
|
if (f != NULL && PyDescr_IsData(descr)) {
|
||||||
return f(descr, obj, value);
|
res = f(descr, obj, value);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dictptr = _PyObject_GetDictPtr(obj);
|
dictptr = _PyObject_GetDictPtr(obj);
|
||||||
|
@ -1276,35 +1325,38 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
|
||||||
if (dict == NULL && value != NULL) {
|
if (dict == NULL && value != NULL) {
|
||||||
dict = PyDict_New();
|
dict = PyDict_New();
|
||||||
if (dict == NULL)
|
if (dict == NULL)
|
||||||
return -1;
|
goto done;
|
||||||
*dictptr = dict;
|
*dictptr = dict;
|
||||||
}
|
}
|
||||||
if (dict != NULL) {
|
if (dict != NULL) {
|
||||||
int res;
|
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
res = PyDict_DelItem(dict, name);
|
res = PyDict_DelItem(dict, name);
|
||||||
else
|
else
|
||||||
res = PyDict_SetItem(dict, name, value);
|
res = PyDict_SetItem(dict, name, value);
|
||||||
if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
|
if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
|
||||||
PyErr_SetObject(PyExc_AttributeError, name);
|
PyErr_SetObject(PyExc_AttributeError, name);
|
||||||
return res;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f != NULL)
|
if (f != NULL) {
|
||||||
return f(descr, obj, value);
|
res = f(descr, obj, value);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (descr == NULL) {
|
if (descr == NULL) {
|
||||||
PyErr_Format(PyExc_AttributeError,
|
PyErr_Format(PyExc_AttributeError,
|
||||||
"'%.50s' object has no attribute '%.400s'",
|
"'%.50s' object has no attribute '%.400s'",
|
||||||
tp->tp_name, PyString_AS_STRING(name));
|
tp->tp_name, PyString_AS_STRING(name));
|
||||||
return -1;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyErr_Format(PyExc_AttributeError,
|
PyErr_Format(PyExc_AttributeError,
|
||||||
"'%.50s' object attribute '%.400s' is read-only",
|
"'%.50s' object attribute '%.400s' is read-only",
|
||||||
tp->tp_name, PyString_AS_STRING(name));
|
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.
|
/* Test a value used as condition, e.g., in a for or if statement.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue