Fix OOB reads in SoftmaxCrossEntropyLoss via label bounds validation
Merged
VR
6mo ago+320+320+012345678901234567890123456789-22-22-01234567890123456789
Description
Fix out-of-bounds reads in SoftmaxCrossEntropyLoss and SoftmaxCrossEntropyLossGrad (CPU EP) when label values are outside [0, C). Same class of bug fixed in #27568 for SparseSoftmaxCrossEntropy.
The CUDA kernels currently only validate labels via CUDA_KERNEL_ASSERT, which is a no-op in release builds. CUDA hardening is not part of this PR.
Changes
- Forward: bounds check folded into the three per-sample loops (after
ignore_indexskip, before anyweight_data[label]/log_prob_data[i*C + label]access). - Backward: single upfront serial bounds check (parallel-for lambdas cannot return Status); comment explains why.
- Validate
weight_shape[0] == C. - Move
weight_data[label]access afterignore_indexcheck in grad weighted paths. N_D * Cwrapped inSafeInt;gsl::narrow<int>forN_DandC. Overflow / truncation returnsINVALID_ARGUMENT.Eigen::Indexsize guard:ORT_ENFORCE->ORT_RETURN_IF.IsScalar(ignore_index)check:ORT_ENFORCE->ORT_RETURN_IF_NOTin both forward and backward.- Pre-existing wrong-sized
memsetin backward (sizeof(T1) * N_D) corrected tosizeof(T1) * probability_shape.Size(). The previous code was effectively redundant (subsequent parallel-for paths overwrite allN_D * Centries) so this is cleanup, not an active OOB. - Renamed
weight_smaple->weight_sample.
Tests
11 regression tests in cross_entropy_test.cc:
- Label too large (forward + grad, int64 + int32)
- Negative label
- Label too large with weights (MEAN and SUM reductions)
- Higher-dim logit
[2,4,2,3]with label[2,2,3] SoftmaxCrossEntropyLossInternalandSoftmaxCrossEntropyLossInternalGradwithignore_indexas a runtime tensor input