@@ -3075,16 +3075,43 @@ type_getattro(PyTypeObject *type, PyObject *name)
3075
3075
static int
3076
3076
type_setattro (PyTypeObject * type , PyObject * name , PyObject * value )
3077
3077
{
3078
+ int res ;
3078
3079
if (!(type -> tp_flags & Py_TPFLAGS_HEAPTYPE )) {
3079
3080
PyErr_Format (
3080
3081
PyExc_TypeError ,
3081
3082
"can't set attributes of built-in/extension type '%s'" ,
3082
3083
type -> tp_name );
3083
3084
return -1 ;
3084
3085
}
3085
- if (PyObject_GenericSetAttr ((PyObject * )type , name , value ) < 0 )
3086
- return -1 ;
3087
- return update_slot (type , name );
3086
+ if (PyUnicode_Check (name )) {
3087
+ if (PyUnicode_CheckExact (name )) {
3088
+ if (PyUnicode_READY (name ) == -1 )
3089
+ return -1 ;
3090
+ Py_INCREF (name );
3091
+ }
3092
+ else {
3093
+ name = _PyUnicode_Copy (name );
3094
+ if (name == NULL )
3095
+ return -1 ;
3096
+ }
3097
+ PyUnicode_InternInPlace (& name );
3098
+ if (!PyUnicode_CHECK_INTERNED (name )) {
3099
+ PyErr_SetString (PyExc_MemoryError ,
3100
+ "Out of memory interning an attribute name" );
3101
+ Py_DECREF (name );
3102
+ return -1 ;
3103
+ }
3104
+ }
3105
+ else {
3106
+ /* Will fail in _PyObject_GenericSetAttrWithDict. */
3107
+ Py_INCREF (name );
3108
+ }
3109
+ res = PyObject_GenericSetAttr ((PyObject * )type , name , value );
3110
+ if (res == 0 ) {
3111
+ res = update_slot (type , name );
3112
+ }
3113
+ Py_DECREF (name );
3114
+ return res ;
3088
3115
}
3089
3116
3090
3117
extern void
@@ -6929,7 +6956,7 @@ init_slotdefs(void)
6929
6956
/* Slots must be ordered by their offset in the PyHeapTypeObject. */
6930
6957
assert (!p [1 ].name || p -> offset <= p [1 ].offset );
6931
6958
p -> name_strobj = PyUnicode_InternFromString (p -> name );
6932
- if (!p -> name_strobj )
6959
+ if (!p -> name_strobj || ! PyUnicode_CHECK_INTERNED ( p -> name_strobj ) )
6933
6960
Py_FatalError ("Out of memory interning slotdef names" );
6934
6961
}
6935
6962
slotdefs_initialized = 1 ;
@@ -6954,6 +6981,9 @@ update_slot(PyTypeObject *type, PyObject *name)
6954
6981
slotdef * * pp ;
6955
6982
int offset ;
6956
6983
6984
+ assert (PyUnicode_CheckExact (name ));
6985
+ assert (PyUnicode_CHECK_INTERNED (name ));
6986
+
6957
6987
/* Clear the VALID_VERSION flag of 'type' and all its
6958
6988
subclasses. This could possibly be unified with the
6959
6989
update_subclasses() recursion below, but carefully:
@@ -6964,7 +6994,6 @@ update_slot(PyTypeObject *type, PyObject *name)
6964
6994
init_slotdefs ();
6965
6995
pp = ptrs ;
6966
6996
for (p = slotdefs ; p -> name ; p ++ ) {
6967
- /* XXX assume name is interned! */
6968
6997
if (p -> name_strobj == name )
6969
6998
* pp ++ = p ;
6970
6999
}
0 commit comments