mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
Make identifiers str (not str8) objects throughout.
This affects the parser, various object implementations, and all places that put identifiers into C string literals. In testing, a number of crashes occurred as code would fail when the recursion limit was reached (such as the Unicode interning dictionary having key/value pairs where key is not value). To solve these, I added an overflowed flag, which allows for 50 more recursions after the limit was reached and the exception was raised, and a recursion_critical flag, which indicates that recursion absolutely must be allowed, i.e. that a certain call must not cause a stack overflow exception. There are still some places where both str and str8 are accepted as identifiers; these should eventually be removed.
This commit is contained in:
parent
38e43c25ee
commit
5b222135f8
40 changed files with 462 additions and 289 deletions
108
Objects/object.c
108
Objects/object.c
|
@ -465,7 +465,7 @@ PyObject_Unicode(PyObject *v)
|
|||
check this before trying the __unicode__
|
||||
method. */
|
||||
if (unicodestr == NULL) {
|
||||
unicodestr= PyString_InternFromString("__unicode__");
|
||||
unicodestr= PyUnicode_InternFromString("__unicode__");
|
||||
if (unicodestr == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
@ -852,7 +852,7 @@ PyObject_GetAttrString(PyObject *v, const char *name)
|
|||
|
||||
if (v->ob_type->tp_getattr != NULL)
|
||||
return (*v->ob_type->tp_getattr)(v, (char*)name);
|
||||
w = PyString_InternFromString(name);
|
||||
w = PyUnicode_InternFromString(name);
|
||||
if (w == NULL)
|
||||
return NULL;
|
||||
res = PyObject_GetAttr(v, w);
|
||||
|
@ -880,7 +880,7 @@ PyObject_SetAttrString(PyObject *v, const char *name, PyObject *w)
|
|||
|
||||
if (v->ob_type->tp_setattr != NULL)
|
||||
return (*v->ob_type->tp_setattr)(v, (char*)name, w);
|
||||
s = PyString_InternFromString(name);
|
||||
s = PyUnicode_InternFromString(name);
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
res = PyObject_SetAttr(v, s, w);
|
||||
|
@ -893,30 +893,19 @@ PyObject_GetAttr(PyObject *v, PyObject *name)
|
|||
{
|
||||
PyTypeObject *tp = v->ob_type;
|
||||
|
||||
if (!PyString_Check(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;
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"attribute name must be string, not '%.200s'",
|
||||
name->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
if (!PyUnicode_Check(name)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"attribute name must be string, not '%.200s'",
|
||||
name->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
if (tp->tp_getattro != NULL)
|
||||
return (*tp->tp_getattro)(v, name);
|
||||
if (tp->tp_getattr != NULL)
|
||||
return (*tp->tp_getattr)(v, PyString_AS_STRING(name));
|
||||
return (*tp->tp_getattr)(v, PyUnicode_AsString(name));
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
"'%.50s' object has no attribute '%.400s'",
|
||||
tp->tp_name, PyString_AS_STRING(name));
|
||||
tp->tp_name, PyUnicode_AsString(name));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -938,33 +927,22 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
|
|||
PyTypeObject *tp = v->ob_type;
|
||||
int err;
|
||||
|
||||
if (!PyString_Check(name)) {
|
||||
/* 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_AsDefaultEncodedString(name, NULL);
|
||||
if (name == NULL)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"attribute name must be string, not '%.200s'",
|
||||
name->ob_type->tp_name);
|
||||
return -1;
|
||||
}
|
||||
if (!PyUnicode_Check(name)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"attribute name must be string, not '%.200s'",
|
||||
name->ob_type->tp_name);
|
||||
return -1;
|
||||
}
|
||||
Py_INCREF(name);
|
||||
|
||||
PyString_InternInPlace(&name);
|
||||
PyUnicode_InternInPlace(&name);
|
||||
if (tp->tp_setattro != NULL) {
|
||||
err = (*tp->tp_setattro)(v, name, value);
|
||||
Py_DECREF(name);
|
||||
return err;
|
||||
}
|
||||
if (tp->tp_setattr != NULL) {
|
||||
err = (*tp->tp_setattr)(v, PyString_AS_STRING(name), value);
|
||||
err = (*tp->tp_setattr)(v, PyUnicode_AsString(name), value);
|
||||
Py_DECREF(name);
|
||||
return err;
|
||||
}
|
||||
|
@ -976,14 +954,14 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
|
|||
"(%s .%.100s)",
|
||||
tp->tp_name,
|
||||
value==NULL ? "del" : "assign to",
|
||||
PyString_AS_STRING(name));
|
||||
PyUnicode_AsString(name));
|
||||
else
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"'%.100s' object has only read-only attributes "
|
||||
"(%s .%.100s)",
|
||||
tp->tp_name,
|
||||
value==NULL ? "del" : "assign to",
|
||||
PyString_AS_STRING(name));
|
||||
PyUnicode_AsString(name));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1033,22 +1011,11 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
|
|||
Py_ssize_t dictoffset;
|
||||
PyObject **dictptr;
|
||||
|
||||
if (!PyString_Check(name)){
|
||||
/* 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
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"attribute name must be string, not '%.200s'",
|
||||
name->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
if (!PyUnicode_Check(name)){
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"attribute name must be string, not '%.200s'",
|
||||
name->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
Py_INCREF(name);
|
||||
|
@ -1134,7 +1101,7 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
|
|||
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
"'%.50s' object has no attribute '%.400s'",
|
||||
tp->tp_name, PyString_AS_STRING(name));
|
||||
tp->tp_name, PyUnicode_AsString(name));
|
||||
done:
|
||||
Py_DECREF(name);
|
||||
return res;
|
||||
|
@ -1149,22 +1116,11 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
|
|||
PyObject **dictptr;
|
||||
int res = -1;
|
||||
|
||||
if (!PyString_Check(name)){
|
||||
/* 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
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"attribute name must be string, not '%.200s'",
|
||||
name->ob_type->tp_name);
|
||||
return -1;
|
||||
}
|
||||
if (!PyUnicode_Check(name)){
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"attribute name must be string, not '%.200s'",
|
||||
name->ob_type->tp_name);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
Py_INCREF(name);
|
||||
|
@ -1212,13 +1168,13 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
|
|||
if (descr == NULL) {
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
"'%.100s' object has no attribute '%.200s'",
|
||||
tp->tp_name, PyString_AS_STRING(name));
|
||||
tp->tp_name, PyUnicode_AsString(name));
|
||||
goto done;
|
||||
}
|
||||
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
"'%.50s' object attribute '%.400s' is read-only",
|
||||
tp->tp_name, PyString_AS_STRING(name));
|
||||
tp->tp_name, PyUnicode_AsString(name));
|
||||
done:
|
||||
Py_DECREF(name);
|
||||
return res;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue