From 292bc2abf3591dcc3b7f4202ca387e06f91b7595 Mon Sep 17 00:00:00 2001 From: Nikita Grigorian Date: Wed, 19 Feb 2025 22:14:02 -0800 Subject: [PATCH 1/2] Fix possible overflows in _usmarray.pyx When a bad typenum is passed to functions which make usm_ndarrays from pointers, there was a possible underflow, as itemsize was declared size_t Instead declare itemsize as int and cast to size_t when needed (as itemsize should always fit in int) --- dpctl/tensor/_usmarray.pyx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/dpctl/tensor/_usmarray.pyx b/dpctl/tensor/_usmarray.pyx index 62cbfd0665..91f14660fb 100644 --- a/dpctl/tensor/_usmarray.pyx +++ b/dpctl/tensor/_usmarray.pyx @@ -1777,8 +1777,10 @@ cdef api object UsmNDArray_MakeSimpleFromPtr( Returns: Created usm_ndarray instance """ - cdef size_t itemsize = type_bytesize(typenum) - cdef size_t nbytes = itemsize * nelems + cdef int itemsize = type_bytesize(typenum) + if (itemsize < 1): + raise ValueError("dtype with typenum=" + str(typenum) + " is not supported.") + cdef size_t nbytes = ( itemsize) * nelems cdef c_dpmem._Memory mobj = c_dpmem._Memory.create_from_usm_pointer_size_qref( ptr, nbytes, QRef, memory_owner=owner ) @@ -1817,7 +1819,7 @@ cdef api object UsmNDArray_MakeFromPtr( Returns: Created usm_ndarray instance """ - cdef size_t itemsize = type_bytesize(typenum) + cdef int itemsize = type_bytesize(typenum) cdef int err = 0 cdef size_t nelems = 1 cdef Py_ssize_t min_disp = 0 @@ -1830,6 +1832,8 @@ cdef api object UsmNDArray_MakeFromPtr( cdef object obj_shape cdef object obj_strides + if (itemsize < 1): + raise ValueError("dtype with typenum=" + str(typenum) + " is not supported.") if (nd < 0): raise ValueError("Dimensionality must be non-negative") if (ptr is NULL or QRef is NULL): @@ -1881,7 +1885,7 @@ cdef api object UsmNDArray_MakeFromPtr( raise ValueError( "Given shape, strides and offset reference out-of-bound memory" ) - nbytes = itemsize * (offset + max_disp + 1) + nbytes = ( itemsize) * (offset + max_disp + 1) mobj = c_dpmem._Memory.create_from_usm_pointer_size_qref( ptr, nbytes, QRef, memory_owner=owner ) From ba7c0904d30762301e2b324db6c76e1149f247a7 Mon Sep 17 00:00:00 2001 From: Nikita Grigorian Date: Thu, 20 Feb 2025 11:14:13 -0800 Subject: [PATCH 2/2] Add test for invalid typenums in usm_ndarray-from-pointer functions --- dpctl/tests/test_usm_ndarray_ctor.py | 69 ++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/dpctl/tests/test_usm_ndarray_ctor.py b/dpctl/tests/test_usm_ndarray_ctor.py index 81b398ab9b..816b48b7b3 100644 --- a/dpctl/tests/test_usm_ndarray_ctor.py +++ b/dpctl/tests/test_usm_ndarray_ctor.py @@ -963,6 +963,75 @@ def test_pyx_capi_make_general(): assert zd_arr._pointer == mat._pointer +def test_pyx_capi_make_fns_invalid_typenum(): + q = get_queue_or_skip() + usm_ndarray = dpt.empty(tuple(), dtype="i4", sycl_queue=q) + + make_simple_from_ptr = _pyx_capi_fnptr_to_callable( + usm_ndarray, + "UsmNDArray_MakeSimpleFromPtr", + b"PyObject *(size_t, int, DPCTLSyclUSMRef, " + b"DPCTLSyclQueueRef, PyObject *)", + fn_restype=ctypes.py_object, + fn_argtypes=( + ctypes.c_size_t, + ctypes.c_int, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.py_object, + ), + ) + + nelems = 10 + dtype = dpt.int64 + arr = dpt.arange(nelems, dtype=dtype, sycl_queue=q) + + with pytest.raises(ValueError): + make_simple_from_ptr( + ctypes.c_size_t(nelems), + -1, + arr._pointer, + arr.sycl_queue.addressof_ref(), + arr, + ) + + make_from_ptr = _pyx_capi_fnptr_to_callable( + usm_ndarray, + "UsmNDArray_MakeFromPtr", + b"PyObject *(int, Py_ssize_t const *, int, Py_ssize_t const *, " + b"DPCTLSyclUSMRef, DPCTLSyclQueueRef, Py_ssize_t, PyObject *)", + fn_restype=ctypes.py_object, + fn_argtypes=( + ctypes.c_int, + ctypes.POINTER(ctypes.c_ssize_t), + ctypes.c_int, + ctypes.POINTER(ctypes.c_ssize_t), + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_ssize_t, + ctypes.py_object, + ), + ) + c_shape = (ctypes.c_ssize_t * 1)( + nelems, + ) + c_strides = (ctypes.c_ssize_t * 1)( + 1, + ) + with pytest.raises(ValueError): + make_from_ptr( + ctypes.c_int(1), + c_shape, + -1, + c_strides, + arr._pointer, + arr.sycl_queue.addressof_ref(), + ctypes.c_ssize_t(0), + arr, + ) + del arr + + def _pyx_capi_int(X, pyx_capi_name, caps_name=b"int", val_restype=ctypes.c_int): import sys