Skip to content

Commit 913cbb9

Browse files
bmehta001Copilot
andcommitted
Validate coefficients size in LinearRegressor to prevent OOB read
LinearRegressor treats the coefficients attribute as a [num_targets, num_features] matrix and passes it directly to MLAS SGEMM. However, num_features is derived from the input tensor at runtime, and no validation ensured coefficients.size() == num_targets * num_features. A malformed model could provide fewer coefficients than expected, causing MlasSgemmTransposePackB to read past the buffer boundary. Add a size check after num_features is computed but before the GEMM dispatch to reject mismatched coefficients with a clear error message. Files changed: - onnxruntime/core/providers/cpu/ml/linearregressor.cc - onnxruntime/test/providers/cpu/ml/linearregressor_test.cc Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 99ad89d commit 913cbb9

2 files changed

Lines changed: 23 additions & 0 deletions

File tree

onnxruntime/core/providers/cpu/ml/linearregressor.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,16 @@ Status LinearRegressor::Compute(OpKernelContext* ctx) const {
8686
ptrdiff_t num_batches = input_shape.NumDimensions() <= 1 ? 1 : narrow<ptrdiff_t>(input_shape[0]);
8787
ptrdiff_t num_features = input_shape.NumDimensions() <= 1 ? narrow<ptrdiff_t>(input_shape.Size())
8888
: narrow<ptrdiff_t>(input_shape[1]);
89+
90+
// Coefficients are treated as a [num_targets, num_features] matrix.
91+
// Validate size to prevent out-of-bounds reads in the GEMM backend.
92+
if (coefficients_.size() != static_cast<size_t>(num_targets_) * static_cast<size_t>(num_features)) {
93+
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
94+
"LinearRegressor: coefficients attribute size (", coefficients_.size(),
95+
") does not match targets (", num_targets_,
96+
") * input features (", num_features, ")");
97+
}
98+
8999
Tensor& Y = *ctx->Output(0, {num_batches, num_targets_});
90100
concurrency::ThreadPool* tp = ctx->GetOperatorThreadPool();
91101

onnxruntime/test/providers/cpu/ml/linearregressor_test.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,18 @@ INSTANTIATE_TEST_SUITE_P(
8585
LinearRegressorParam("SOFTMAX_ZERO", {3.442477e-14f, 1.f, 1.670142e-05f, 1.f, 1.0f, 0.f}, 2)
8686

8787
));
88+
89+
// Regression test: coefficients size must match targets * num_features.
90+
// A mismatch previously caused an out-of-bounds read in MLAS SGEMM packing.
91+
TEST(LinearRegressorTest, CoefficientsSizeMismatch) {
92+
OpTester test("LinearRegressor", 1, onnxruntime::kMLDomain);
93+
// 1 coefficient but input has 2 features and targets=1 → expects 2 coefficients
94+
test.AddAttribute("coefficients", std::vector<float>{1.0f});
95+
test.AddAttribute("targets", int64_t{1});
96+
test.AddInput<float>("X", {1, 2}, {1.f, 2.f});
97+
test.AddOutput<float>("Y", {1, 1}, {0.f});
98+
test.Run(OpTester::ExpectResult::kExpectFailure, "coefficients attribute size");
99+
}
100+
88101
} // namespace test
89102
} // namespace onnxruntime

0 commit comments

Comments
 (0)