From 9449187fa81a5b86830c5eb961dfe1d2be7b88fa Mon Sep 17 00:00:00 2001 From: lvllvl <24905907+lvllvl@users.noreply.github.com> Date: Fri, 28 Feb 2025 23:20:08 +0000 Subject: [PATCH] BUG: Prevent segmentation fault in np.asanyarray --- numpy/_core/src/multiarray/ctors.c | 8 +++++++- numpy/_core/tests/test_multiarray.py | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/numpy/_core/src/multiarray/ctors.c b/numpy/_core/src/multiarray/ctors.c index 383aa200e21d..31aa74822494 100644 --- a/numpy/_core/src/multiarray/ctors.c +++ b/numpy/_core/src/multiarray/ctors.c @@ -2134,7 +2134,7 @@ PyArray_FromInterface(PyObject *origin) PyArray_Descr *dtype = NULL; char *data = NULL; Py_buffer view; - int i, n; + Py_ssize_t i, n; npy_intp dims[NPY_MAXDIMS], strides[NPY_MAXDIMS]; int dataflags = NPY_ARRAY_BEHAVED; @@ -2250,6 +2250,12 @@ PyArray_FromInterface(PyObject *origin) /* Get dimensions from shape tuple */ else { n = PyTuple_GET_SIZE(attr); + if (n > NPY_MAXDIMS) { + PyErr_Format(PyExc_ValueError, + "number of dimensions must be within [0, %d], got %d", + NPY_MAXDIMS, n); + goto fail; + } for (i = 0; i < n; i++) { PyObject *tmp = PyTuple_GET_ITEM(attr, i); dims[i] = PyArray_PyIntAsIntp(tmp); diff --git a/numpy/_core/tests/test_multiarray.py b/numpy/_core/tests/test_multiarray.py index 3de42ba8ed80..481dc5c2ec81 100644 --- a/numpy/_core/tests/test_multiarray.py +++ b/numpy/_core/tests/test_multiarray.py @@ -10420,3 +10420,24 @@ def test_to_device(self): r"The stream argument in to_device\(\) is not supported" ): arr.to_device("cpu", stream=1) + +def test_array_interface_excess_dimensions_raises(): + """Regression test for gh-27949: ensure too many dims raises ValueError instead of segfault.""" + + # Dummy object to hold a custom __array_interface__ + class DummyArray: + def __init__(self, interface): + # Attach the array interface dict to mimic an array + self.__array_interface__ = interface + + # Create a base array (scalar) and copy its interface + base = np.array(42) # base can be any scalar or array + interface = dict(base.__array_interface__) + + # Modify the shape to exceed NumPy's dimension limit (NPY_MAXDIMS, typically 64) + interface['shape'] = tuple([1] * 136) # match the original bug report + + dummy = DummyArray(interface) + # Now, using np.asanyarray on this dummy should trigger a ValueError (not segfault) + with pytest.raises(ValueError, match="dimensions must be within"): + np.asanyarray(dummy) \ No newline at end of file