Skip to content

Commit 7f0ebda

Browse files
authored
BUG: sanity check __array_interface__ number of dimensions (numpy#28407)
``__array_interface__`` should typically not have more dimensions than NumPy supports, but unlike other malformed interfaces, this should fail gracefully if someone were to pass more.
1 parent 01e98f1 commit 7f0ebda

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

numpy/_core/src/multiarray/ctors.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2138,7 +2138,7 @@ PyArray_FromInterface(PyObject *origin)
21382138
PyArray_Descr *dtype = NULL;
21392139
char *data = NULL;
21402140
Py_buffer view;
2141-
int i, n;
2141+
Py_ssize_t i, n;
21422142
npy_intp dims[NPY_MAXDIMS], strides[NPY_MAXDIMS];
21432143
int dataflags = NPY_ARRAY_BEHAVED;
21442144

@@ -2254,6 +2254,12 @@ PyArray_FromInterface(PyObject *origin)
22542254
/* Get dimensions from shape tuple */
22552255
else {
22562256
n = PyTuple_GET_SIZE(attr);
2257+
if (n > NPY_MAXDIMS) {
2258+
PyErr_Format(PyExc_ValueError,
2259+
"number of dimensions must be within [0, %d], got %d",
2260+
NPY_MAXDIMS, n);
2261+
goto fail;
2262+
}
22572263
for (i = 0; i < n; i++) {
22582264
PyObject *tmp = PyTuple_GET_ITEM(attr, i);
22592265
dims[i] = PyArray_PyIntAsIntp(tmp);

numpy/_core/tests/test_multiarray.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10420,3 +10420,24 @@ def test_to_device(self):
1042010420
r"The stream argument in to_device\(\) is not supported"
1042110421
):
1042210422
arr.to_device("cpu", stream=1)
10423+
10424+
def test_array_interface_excess_dimensions_raises():
10425+
"""Regression test for gh-27949: ensure too many dims raises ValueError instead of segfault."""
10426+
10427+
# Dummy object to hold a custom __array_interface__
10428+
class DummyArray:
10429+
def __init__(self, interface):
10430+
# Attach the array interface dict to mimic an array
10431+
self.__array_interface__ = interface
10432+
10433+
# Create a base array (scalar) and copy its interface
10434+
base = np.array(42) # base can be any scalar or array
10435+
interface = dict(base.__array_interface__)
10436+
10437+
# Modify the shape to exceed NumPy's dimension limit (NPY_MAXDIMS, typically 64)
10438+
interface['shape'] = tuple([1] * 136) # match the original bug report
10439+
10440+
dummy = DummyArray(interface)
10441+
# Now, using np.asanyarray on this dummy should trigger a ValueError (not segfault)
10442+
with pytest.raises(ValueError, match="dimensions must be within"):
10443+
np.asanyarray(dummy)

0 commit comments

Comments
 (0)