diff options
Diffstat (limited to 'Objects/typeobject.c')
-rw-r--r-- | Objects/typeobject.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 3494fa9..eb5f5a4 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2687,6 +2687,7 @@ type_getattro(PyTypeObject *type, PyObject *name) static int type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) { + int res; if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { PyErr_Format( PyExc_TypeError, @@ -2694,9 +2695,39 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) type->tp_name); return -1; } - if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0) - return -1; - return update_slot(type, name); +#ifdef Py_USING_UNICODE + if (PyUnicode_Check(name)) { + name = PyUnicode_AsEncodedString(name, NULL, NULL); + if (name == NULL) + return -1; + } + else +#endif + Py_INCREF(name); + + if (PyString_Check(name)) { + if (!PyString_CheckExact(name)) { + Py_SETREF(name, + PyString_FromStringAndSize(PyString_AS_STRING(name), + PyString_GET_SIZE(name)) + ); + if (name == NULL) + return -1; + } + PyString_InternInPlace(&name); + if (!PyString_CHECK_INTERNED(name)) { + PyErr_SetString(PyExc_MemoryError, + "Out of memory interning an attribute name"); + Py_DECREF(name); + return -1; + } + } + res = PyObject_GenericSetAttr((PyObject *)type, name, value); + if (res == 0) { + res = update_slot(type, name); + } + Py_DECREF(name); + return res; } static void @@ -6355,7 +6386,7 @@ init_slotdefs(void) /* Slots must be ordered by their offset in the PyHeapTypeObject. */ assert(!p[1].name || p->offset <= p[1].offset); p->name_strobj = PyString_InternFromString(p->name); - if (!p->name_strobj) + if (!p->name_strobj || !PyString_CHECK_INTERNED(p->name_strobj)) Py_FatalError("Out of memory interning slotdef names"); } initialized = 1; @@ -6370,6 +6401,9 @@ update_slot(PyTypeObject *type, PyObject *name) slotdef **pp; int offset; + assert(PyString_CheckExact(name)); + assert(PyString_CHECK_INTERNED(name)); + /* Clear the VALID_VERSION flag of 'type' and all its subclasses. This could possibly be unified with the update_subclasses() recursion below, but carefully: @@ -6380,7 +6414,6 @@ update_slot(PyTypeObject *type, PyObject *name) init_slotdefs(); pp = ptrs; for (p = slotdefs; p->name; p++) { - /* XXX assume name is interned! */ if (p->name_strobj == name) *pp++ = p; } |