@@ -1097,6 +1097,28 @@ CDataType_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value)
10971097 return Py_NewRef (value );
10981098 }
10991099 ctypes_state * st = get_module_state_by_class (cls );
1100+
1101+ /* Disallow incompatible ctypes array __class__ reassignment */
1102+ StgInfo * old_info = NULL ;
1103+ StgInfo * new_info = NULL ;
1104+ if (PyStgInfo_FromObject (st , value , & old_info ) == 0 &&
1105+ PyStgInfo_FromType (st , type , & new_info ) == 0 &&
1106+ old_info != NULL &&
1107+ new_info != NULL &&
1108+ old_info -> length >= 0 &&
1109+ new_info -> length >= 0 )
1110+ {
1111+ if (old_info -> length != new_info -> length ||
1112+ old_info -> size != new_info -> size ||
1113+ old_info -> proto != new_info -> proto )
1114+ {
1115+ PyErr_SetString (
1116+ PyExc_TypeError ,
1117+ "cannot assign incompatible ctypes array type"
1118+ );
1119+ return NULL ;
1120+ }
1121+ }
11001122 if (PyCArg_CheckExact (st , value )) {
11011123 PyCArgObject * p = (PyCArgObject * )value ;
11021124 PyObject * ob = p -> obj ;
@@ -4992,6 +5014,41 @@ Array_init(PyObject *self, PyObject *args, PyObject *kw)
49925014 return 0 ;
49935015}
49945016
5017+ static int
5018+ PyCArray_setattro (PyObject * self , PyObject * key , PyObject * value )
5019+ {
5020+ if (PyUnicode_Check (key ) &&
5021+ PyUnicode_CompareWithASCIIString (key , "__class__" ) == 0 )
5022+ {
5023+ ctypes_state * st = get_module_state_by_def (Py_TYPE (Py_TYPE (self )));
5024+ StgInfo * old_info ;
5025+ StgInfo * new_info ;
5026+
5027+ if (PyStgInfo_FromObject (st , self , & old_info ) < 0 ) {
5028+ return -1 ;
5029+ }
5030+ if (PyStgInfo_FromType (st , value , & new_info ) < 0 ) {
5031+ return -1 ;
5032+ }
5033+
5034+ /* Only care about array → array */
5035+ if (old_info -> length >= 0 && new_info -> length >= 0 ) {
5036+ if (old_info -> length != new_info -> length ||
5037+ old_info -> size != new_info -> size ||
5038+ old_info -> proto != new_info -> proto )
5039+ {
5040+ PyErr_SetString (
5041+ PyExc_TypeError ,
5042+ "cannot assign incompatible ctypes array type"
5043+ );
5044+ return -1 ;
5045+ }
5046+ }
5047+ }
5048+
5049+ return PyObject_GenericSetAttr (self , key , value );
5050+ }
5051+
49955052static PyObject *
49965053Array_item_lock_held (PyObject * myself , Py_ssize_t index )
49975054{
@@ -5310,6 +5367,7 @@ static PyType_Slot pycarray_slots[] = {
53105367 {Py_mp_length , Array_length },
53115368 {Py_mp_subscript , Array_subscript },
53125369 {Py_mp_ass_subscript , Array_ass_subscript },
5370+ {Py_tp_setattro , PyCArray_setattro },
53135371 {0 , NULL },
53145372};
53155373
0 commit comments