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 onnxruntime/python/onnxruntime_inference_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,7 @@ def update_inplace(self, np_arr) -> None:
enabled or other scenarios where the OrtValue needs to be updated while
the memory address can not be changed.
"""
np_arr = np.ascontiguousarray(np_arr)
self._ortvalue.update_inplace(np_arr)
Comment on lines +1178 to 1179
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

np.ascontiguousarray(np_arr) will also accept non-ndarray inputs (e.g., Python lists) and silently convert them to a NumPy array. That changes the previous API behavior (pybind would have rejected non-py::array inputs) and can lead to silent data corruption if the inferred dtype doesn’t match the OrtValue’s tensor element type (the C++ update_inplace path copies raw bytes based on the tensor type, without validating the NumPy dtype). Consider validating np_arr is a np.ndarray (and ideally that its dtype matches the OrtValue element type) before making/using a contiguous copy, so callers still get an error instead of a potentially-wrong update.

Copilot uses AI. Check for mistakes.


Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change fixes behavior for non-contiguous arrays but there’s no regression test covering it. Please add a Python unit test that calls OrtValue.update_inplace() with a non-contiguous NumPy view (e.g., created via transpose/slicing) and asserts that round-tripping via .numpy() matches the original values (CPU-only is sufficient; optionally cover CUDA/DML when available).

Suggested change
def test_ortvalue_update_inplace_non_contiguous_numpy_view_cpu_only() -> None:
"""
Regression test for OrtValue.update_inplace with a non-contiguous NumPy view.
Verifies that updating an OrtValue in-place with a non-contiguous view
(e.g., produced via transpose/slicing) correctly copies the values into
the underlying tensor, and that round-tripping via .numpy() matches
the original view values.
"""
import numpy as np
# Create a base contiguous array and an OrtValue backed by it on CPU.
base = np.arange(24, dtype=np.float32).reshape(2, 3, 4)
ort_value = OrtValue.ortvalue_from_numpy(base, "cpu", 0)
# Create a non-contiguous view via transpose and slicing.
non_contiguous_view = base.transpose(2, 0, 1)[::2]
# Update the OrtValue in-place with the non-contiguous view.
ort_value.update_inplace(non_contiguous_view)
# Round-trip the data back to NumPy and ensure values match the view.
result = ort_value.numpy()
np.testing.assert_allclose(result, np.asarray(non_contiguous_view))

Copilot uses AI. Check for mistakes.
Expand Down
10 changes: 10 additions & 0 deletions onnxruntime/test/python/onnxruntime_test_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -2035,6 +2035,16 @@ def test_get_graph_provider_assignment_info_not_enabled(self):
"Session configuration entry 'session.record_ep_graph_assignment_info' must be set to \"1\"",
str(context.exception),
)
def test_update_inplace_non_contiguous(self):
"""
Regression test for OrtValue.update_inplace with non-contiguous NumPy view.
"""
base = np.arange(24, dtype=np.float32).reshape(2, 3, 4)
ort_val = onnxrt.OrtValue.ortvalue_from_numpy(base, "cpu", 0)
non_contiguous_view = base.transpose(2, 0, 1)[::2]
ort_val.update_inplace(non_contiguous_view)
result = ort_val.numpy()
np.testing.assert_allclose(result, np.asarray(non_contiguous_view))


if __name__ == "__main__":
Expand Down