Harden OneHot operator input validation and output size computation
Merged
GO
6mo ago+169+169+012345678901234567890123456789-6-6-0123456789
Harden OneHot operator input validation and output size computation
Summary
This PR tightens input validation and output-shape computation for the OneHot operator on the CPU and CUDA execution providers so that invalid or extreme inputs fail cleanly with an INVALID_ARGUMENT status instead of triggering overflow, silent truncation, or division by zero.
Changes
-
Overflow check in
PrepareOutputShapeusingSafeInt- The output tensor size computation now uses a checked multiplication over the output dimensions, and the
prefix_dim_sizemultiplication loop is rewritten withSafeInt<int64_t>. This prevents unbounded allocation attempts when a largedepthvalue (or largeindicesshape) would overflowint64_t.
- The output tensor size computation now uses a checked multiplication over the output dimensions, and the
-
Guard against division by zero when
prefix_dim_sizeis zerosuffix_dim_sizeis now computed as(prefix_dim_size > 0) ? (indices_shape.Size() / prefix_dim_size) : 0, avoiding an integer division by zero when an indices dimension before the axis is zero.
-
CUDA int32 range validation before
fast_divmod- Before narrowing to
intforfast_divmod(which requiresint32operands), the kernel now validates thatsuffix_dim_sizeanddepth_val * suffix_dim_sizefit inint32_t. Previouslygsl::narrow_cast<int>could silently truncate, producing wrong divmod operands.
- Before narrowing to
-
nullptrcheck onOutput()in both CPU and CUDAComputepaths- If allocation of the output tensor fails (e.g., because the requested shape is too large for the allocator), both kernels now return a descriptive error instead of dereferencing a null pointer.
-
Unit tests in
onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc:DepthTooLarge_OutputSizeOverflow—depth = INT64_MAX,indices = [2,3].DepthTooLarge_OutputSizeOverflow_LargeIndices—depth = INT64_MAX / 500,indices = [1000].NegativeDepth— negative depth is rejected.DepthOne— minimum validdepth = 1edge case.ScalarIndicesRejected— rank-0 indices are rejected per the ONNX spec (indices rank ≥ 1).DefaultAxis_Opset9— opset 9 coverage for the default-axis path.- The three negative-path tests exclude
kTensorrtExecutionProviderandkDmlExecutionProviderbecause those EPs fail with their own (different) error messages before our kernel validation runs.
Files touched
onnxruntime/core/providers/cpu/tensor/onehot.cc | 28 +++++++-
onnxruntime/core/providers/cuda/tensor/onehot.cc | 13 ++++
onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc | 83 ++++++++++++++++++++++
Testing
Built onnxruntime_provider_test on Windows (Release) and ran OneHotOpTest.*:
[==========] 34 tests from 1 test suite ran.
[ PASSED ] 34 tests.
Overflow tests produce the expected error, for example:
OneHot: output tensor size would overflow for the given indices shape and depth value (9223372036854775807).