@@ -3020,16 +3020,43 @@ type_getattro(PyTypeObject *type, PyObject *name)
3020
3020
static int
3021
3021
type_setattro (PyTypeObject * type , PyObject * name , PyObject * value )
3022
3022
{
3023
+ int res ;
3023
3024
if (!(type -> tp_flags & Py_TPFLAGS_HEAPTYPE )) {
3024
3025
PyErr_Format (
3025
3026
PyExc_TypeError ,
3026
3027
"can't set attributes of built-in/extension type '%s'" ,
3027
3028
type -> tp_name );
3028
3029
return -1 ;
3029
3030
}
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 ;
3033
3060
}
3034
3061
3035
3062
extern void
@@ -6849,7 +6876,7 @@ init_slotdefs(void)
6849
6876
/* Slots must be ordered by their offset in the PyHeapTypeObject. */
6850
6877
assert (!p [1 ].name || p -> offset <= p [1 ].offset );
6851
6878
p -> name_strobj = PyUnicode_InternFromString (p -> name );
6852
- if (!p -> name_strobj )
6879
+ if (!p -> name_strobj || ! PyUnicode_CHECK_INTERNED ( p -> name_strobj ) )
6853
6880
Py_FatalError ("Out of memory interning slotdef names" );
6854
6881
}
6855
6882
slotdefs_initialized = 1 ;
@@ -6874,6 +6901,9 @@ update_slot(PyTypeObject *type, PyObject *name)
6874
6901
slotdef * * pp ;
6875
6902
int offset ;
6876
6903
6904
+ assert (PyUnicode_CheckExact (name ));
6905
+ assert (PyUnicode_CHECK_INTERNED (name ));
6906
+
6877
6907
/* Clear the VALID_VERSION flag of 'type' and all its
6878
6908
subclasses. This could possibly be unified with the
6879
6909
update_subclasses() recursion below, but carefully:
@@ -6884,7 +6914,6 @@ update_slot(PyTypeObject *type, PyObject *name)
6884
6914
init_slotdefs ();
6885
6915
pp = ptrs ;
6886
6916
for (p = slotdefs ; p -> name ; p ++ ) {
6887
- /* XXX assume name is interned! */
6888
6917
if (p -> name_strobj == name )
6889
6918
* pp ++ = p ;
6890
6919
}
0 commit comments