@@ -3020,16 +3020,43 @@ type_getattro(PyTypeObject *type, PyObject *name)
30203020static int
30213021type_setattro (PyTypeObject * type , PyObject * name , PyObject * value )
30223022{
3023+ int res ;
30233024 if (!(type -> tp_flags & Py_TPFLAGS_HEAPTYPE )) {
30243025 PyErr_Format (
30253026 PyExc_TypeError ,
30263027 "can't set attributes of built-in/extension type '%s'" ,
30273028 type -> tp_name );
30283029 return -1 ;
30293030 }
3030- if (PyObject_GenericSetAttr ((PyObject * )type , name , value ) < 0 )
3031- return -1 ;
3032- return update_slot (type , name );
3031+ if (PyUnicode_Check (name )) {
3032+ if (PyUnicode_CheckExact (name )) {
3033+ if (PyUnicode_READY (name ) == -1 )
3034+ return -1 ;
3035+ Py_INCREF (name );
3036+ }
3037+ else {
3038+ name = _PyUnicode_Copy (name );
3039+ if (name == NULL )
3040+ return -1 ;
3041+ }
3042+ PyUnicode_InternInPlace (& name );
3043+ if (!PyUnicode_CHECK_INTERNED (name )) {
3044+ PyErr_SetString (PyExc_MemoryError ,
3045+ "Out of memory interning an attribute name" );
3046+ Py_DECREF (name );
3047+ return -1 ;
3048+ }
3049+ }
3050+ else {
3051+ /* Will fail in _PyObject_GenericSetAttrWithDict. */
3052+ Py_INCREF (name );
3053+ }
3054+ res = PyObject_GenericSetAttr ((PyObject * )type , name , value );
3055+ if (res == 0 ) {
3056+ res = update_slot (type , name );
3057+ }
3058+ Py_DECREF (name );
3059+ return res ;
30333060}
30343061
30353062extern void
@@ -6849,7 +6876,7 @@ init_slotdefs(void)
68496876 /* Slots must be ordered by their offset in the PyHeapTypeObject. */
68506877 assert (!p [1 ].name || p -> offset <= p [1 ].offset );
68516878 p -> name_strobj = PyUnicode_InternFromString (p -> name );
6852- if (!p -> name_strobj )
6879+ if (!p -> name_strobj || ! PyUnicode_CHECK_INTERNED ( p -> name_strobj ) )
68536880 Py_FatalError ("Out of memory interning slotdef names" );
68546881 }
68556882 slotdefs_initialized = 1 ;
@@ -6874,6 +6901,9 @@ update_slot(PyTypeObject *type, PyObject *name)
68746901 slotdef * * pp ;
68756902 int offset ;
68766903
6904+ assert (PyUnicode_CheckExact (name ));
6905+ assert (PyUnicode_CHECK_INTERNED (name ));
6906+
68776907 /* Clear the VALID_VERSION flag of 'type' and all its
68786908 subclasses. This could possibly be unified with the
68796909 update_subclasses() recursion below, but carefully:
@@ -6884,7 +6914,6 @@ update_slot(PyTypeObject *type, PyObject *name)
68846914 init_slotdefs ();
68856915 pp = ptrs ;
68866916 for (p = slotdefs ; p -> name ; p ++ ) {
6887- /* XXX assume name is interned! */
68886917 if (p -> name_strobj == name )
68896918 * pp ++ = p ;
68906919 }
0 commit comments