@@ -287,7 +287,7 @@ _convert_from_tuple(PyObject *obj)
287
287
type -> elsize = itemsize ;
288
288
}
289
289
}
290
- else if (PyDict_Check (val ) || PyDictProxy_Check (val )) {
290
+ else if (type -> metadata && ( PyDict_Check (val ) || PyDictProxy_Check (val ) )) {
291
291
/* Assume it's a metadata dictionary */
292
292
if (PyDict_Merge (type -> metadata , val , 0 ) == -1 ) {
293
293
Py_DECREF (type );
@@ -772,6 +772,54 @@ _is_tuple_of_integers(PyObject *obj)
772
772
return 1 ;
773
773
}
774
774
775
+ /*
776
+ * helper function for _use_inherit to disallow dtypes of the form
777
+ * (old_dtype, new_dtype) where either of the dtypes contains python
778
+ * objects - these dtypes are not useful and can be a source of segfaults,
779
+ * when an attempt is made to interpret a python object as a different dtype
780
+ * or vice versa
781
+ * an exception is made for dtypes of the form ('O', [('name', 'O')]), which
782
+ * people have been using to add a field to an object array without fields
783
+ */
784
+ static int
785
+ invalid_union_object_dtype (PyArray_Descr * new , PyArray_Descr * conv )
786
+ {
787
+ PyObject * name , * tup ;
788
+ PyArray_Descr * dtype ;
789
+
790
+ if (!PyDataType_REFCHK (new ) && !PyDataType_REFCHK (conv )) {
791
+ return 0 ;
792
+ }
793
+ if (PyDataType_HASFIELDS (new ) || new -> kind != 'O' ) {
794
+ goto fail ;
795
+ }
796
+ if (!PyDataType_HASFIELDS (conv ) || PyTuple_GET_SIZE (conv -> names ) != 1 ) {
797
+ goto fail ;
798
+ }
799
+ name = PyTuple_GET_ITEM (conv -> names , 0 );
800
+ if (name == NULL ) {
801
+ return -1 ;
802
+ }
803
+ tup = PyDict_GetItem (conv -> fields , name );
804
+ if (tup == NULL ) {
805
+ return -1 ;
806
+ }
807
+ dtype = (PyArray_Descr * )PyTuple_GET_ITEM (tup , 0 );
808
+ if (dtype == NULL ) {
809
+ return -1 ;
810
+ }
811
+ if (dtype -> kind != 'O' ) {
812
+ goto fail ;
813
+ }
814
+ return 0 ;
815
+
816
+ fail :
817
+ PyErr_SetString (PyExc_ValueError ,
818
+ "dtypes of the form (old_dtype, new_dtype) containing the object "
819
+ "dtype are not supported" );
820
+ return -1 ;
821
+ }
822
+
775
823
/*
776
824
* A tuple type would be either (generic typeobject, typesize)
777
825
* or (fixed-length data-type, shape)
@@ -809,6 +857,9 @@ _use_inherit(PyArray_Descr *type, PyObject *newobj, int *errflag)
809
857
"mismatch in size of old and new data-descriptor" );
810
858
goto fail ;
811
859
}
860
+ if (new -> elsize && invalid_union_object_dtype (new , conv )) {
861
+ goto fail ;
862
+ }
812
863
new -> elsize = conv -> elsize ;
813
864
if (PyDataType_HASFIELDS (conv )) {
814
865
Py_XDECREF (new -> fields );
@@ -999,7 +1050,7 @@ _convert_from_dict(PyObject *obj, int align)
999
1050
|| (offsets && (n > PyObject_Length (offsets )))
1000
1051
|| (titles && (n > PyObject_Length (titles )))) {
1001
1052
PyErr_SetString (PyExc_ValueError ,
1002
- "'names', 'formats', 'offsets', and 'titles' dicct "
1053
+ "'names', 'formats', 'offsets', and 'titles' dict "
1003
1054
"entries must have the same length" );
1004
1055
goto fail ;
1005
1056
}
0 commit comments