diff --git a/onnxruntime/core/providers/cpu/tensor/split.cc b/onnxruntime/core/providers/cpu/tensor/split.cc index 7f50f3cea0e80..92911103280e7 100644 --- a/onnxruntime/core/providers/cpu/tensor/split.cc +++ b/onnxruntime/core/providers/cpu/tensor/split.cc @@ -79,6 +79,8 @@ Status SplitImpl::Compute(OpKernelContext* context) const { auto nDims = static_cast(split_tensor->Shape()[0]); const auto* data = split_tensor->Data(); split_sizes.assign(data, data + nDims); + ORT_RETURN_IF(std::any_of(split_sizes.cbegin(), split_sizes.cend(), [](int64_t v) { return v < 0; }), + "Invalid value in 'split' input. All values must be >= 0."); } else { split_sizes.assign(split_sizes_.begin(), split_sizes_.end()); } diff --git a/onnxruntime/test/providers/cpu/tensor/split_op_test.cc b/onnxruntime/test/providers/cpu/tensor/split_op_test.cc index 8db1c4d1fef2e..bb0a945612188 100644 --- a/onnxruntime/test/providers/cpu/tensor/split_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/split_op_test.cc @@ -5,6 +5,7 @@ #include "core/framework/to_tensor_proto_element_type.h" #include "test/providers/provider_test_utils.h" #include "test/common/tensor_op_test_utils.h" +#include "test/util/include/default_providers.h" namespace onnxruntime { namespace test { @@ -910,5 +911,43 @@ TEST(SplitOperatorTest, Split3Inner) { do_test(splits); } +TEST(SplitOperatorTest, InvalidValueInSplitInput_NegativeEntry_Axis0) { + // Force CPU-only execution: the negative-value guard lives in the CPU Split kernel + // Other EPs (CUDA, TensorRT, etc.) have their own Split implementations + // that either fail with a different error or hit the framework's negative-shape check + // downstream. + OpTester test("Split", 13, onnxruntime::kOnnxDomain); + test.AddAttribute("axis", 0); + test.AddInput("input", {6, 2}, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f}); + // Sum equals axis dim (8 + -2 == 6) and count matches num outputs, so existing + // count/sum guards do not trigger; only the per-value check can catch this case. + test.AddInput("split", {2}, {8, -2}, /*is_initializer=*/false); + test.AddOutput("output0", {1, 2}, {0.f, 0.f}); + test.AddOutput("output1", {1, 2}, {0.f, 0.f}); + + std::vector> execution_providers; + execution_providers.push_back(DefaultCpuExecutionProvider()); + test.Run(OpTester::ExpectResult::kExpectFailure, + "Invalid value in 'split' input. All values must be >= 0.", + {}, nullptr, &execution_providers); +} + +TEST(SplitOperatorTest, InvalidValueInSplitInput_NegativeEntry_NegativeAxis) { + // Same reason as above: force CPU-only. Negative entry in the leading position; + // sum still matches the split-axis dim (-1 + 5 == 4). + OpTester test("Split", 13, onnxruntime::kOnnxDomain); + test.AddAttribute("axis", -1); + test.AddInput("input", {2, 4}, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f}); + test.AddInput("split", {2}, {-1, 5}, /*is_initializer=*/false); + test.AddOutput("output0", {2, 1}, {0.f, 0.f}); + test.AddOutput("output1", {2, 1}, {0.f, 0.f}); + + std::vector> execution_providers; + execution_providers.push_back(DefaultCpuExecutionProvider()); + test.Run(OpTester::ExpectResult::kExpectFailure, + "Invalid value in 'split' input. All values must be >= 0.", + {}, nullptr, &execution_providers); +} + } // namespace test } // namespace onnxruntime