Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ This release is compatible with NumPy 2.5.
* Fixed `dpnp.ndarray.view` ignoring the USM element offset of a sliced array, which also caused `dpnp.einsum` to silently return wrong results for a single sliced operand with no summed index [#3037](https://github.com/IntelPython/dpnp/pull/3037)
* Fixed `dpnp.all` and `dpnp.any` aborting when reducing over an empty axis (e.g. an array with a zero-length dimension) [#3021](https://github.com/IntelPython/dpnp/pull/3021)
* Released the GIL before the blocking OneMKL DFT calls in the FFT extension [#3040](https://github.com/IntelPython/dpnp/pull/3040)
* Fixed `dpnp.insert` silently ignoring out-of-bounds negative indices in a multi-element `obj`, so a mix of in-bounds and out-of-bounds indices now consistently raises `IndexError` [#3041](https://github.com/IntelPython/dpnp/pull/3041)

### Security

Expand Down
9 changes: 9 additions & 0 deletions dpnp/dpnp_iface_manipulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,15 @@ def _insert_array_indices(parameters, indices, values, obj):
# Can safely cast the empty list to intp
indices = indices.astype(dpnp.intp)

if indices.size > 0:
min_idx = int(indices.min())
max_idx = int(indices.max())
if min_idx < -n or max_idx > n:
oob = min_idx if min_idx < -n else max_idx
raise IndexError(
f"index {oob} is out of bounds for axis {axis} with size {n}"
)

indices[indices < 0] += n

numnew = len(indices)
Expand Down
29 changes: 25 additions & 4 deletions dpnp/tests/test_manipulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -815,11 +815,32 @@ def test_error(self):
with pytest.raises(TypeError):
dpnp.insert(a, [], 2, axis="nonsense")

@pytest.mark.parametrize("idx", [4, -4])
def test_index_out_of_bounds(self, idx):
a = dpnp.array([0, 1, 2])
@testing.with_requires("numpy>=2.6")
@pytest.mark.parametrize("xp", [numpy, dpnp])
@pytest.mark.parametrize(
"idx, values",
[
# single-element obj -> singleton path
([4], [3, 4]),
([-4], [3, 4]),
# multi-element obj -> array path
([-6, 0], [9, 8]),
([0, 6], [9, 8]),
([4, 4], [3, 4]),
([-4, -5], [3, 4]),
],
)
def test_index_out_of_bounds(self, xp, idx, values):
a = xp.array([0, 1, 2])
with pytest.raises(IndexError, match="out of bounds"):
xp.insert(a, idx, values)

@pytest.mark.parametrize("xp", [numpy, dpnp])
@pytest.mark.parametrize("axis", [0, 1])
def test_index_out_of_bounds_ndim(self, xp, axis):
a = xp.ones((3, 3))
with pytest.raises(IndexError, match="out of bounds"):
dpnp.insert(a, [idx], [3, 4])
xp.insert(a, [5, 0], 9, axis=axis)


# array_split has more comprehensive test of splitting.
Expand Down
Loading