Skip to content

[WIP] ORT aborts with the linspace implementation when input is empty #25065

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jun 14, 2025

Fix ORT abort with linspace implementation when input is empty

Analysis

  • Explore repository structure and understand the issue
  • Reproduce the issue: confirmed it's a floating point exception (abort) during division by zero
  • Identify the root cause: The issue occurs in the Div operation when dividing by zero with integer types
  • Locate relevant source files: onnxruntime/core/providers/cpu/math/element_wise_ops.cc
  • Understand the current implementation uses Eigen arithmetic which doesn't check for division by zero

Implementation

  • Added #include <type_traits> for compile-time type checking
  • Created CheckDivisionByZero<T>() helper function that:
    • Uses if constexpr (std::is_integral_v<T>) to only check integer types
    • Iterates through denominator tensor to detect any zero values
    • Returns proper error status instead of allowing SIGFPE
  • Modified Div<T>::Compute() to call validation before performing division
  • Added comprehensive test cases for both integer and floating point division by zero
  • Verified code compiles successfully
  • Validated logic with standalone tests

Changes Summary

  • 25 lines added to onnxruntime/core/providers/cpu/math/element_wise_ops.cc
  • 44 lines added to onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc
  • Total: 69 lines added, 0 deleted (minimal surgical changes)

Root Cause

The linspace implementation creates a model that performs division by zero:

  1. Range(0, 1, 1) produces [0]
  2. Sub(1, 1) produces 0
  3. Div(1, 0) attempts to divide by zero, causing floating point exception instead of proper error message

Solution

For integer types (int32_t, int64_t, etc.), division by zero now returns:
INVALID_ARGUMENT: "Division by zero error in Div operator"

For floating point types (float, double), behavior remains unchanged (produces infinity per IEEE 754).

Testing & Validation

  • Standalone validation confirms logic works correctly
  • Integer division by zero detected and returns proper error
  • Float division by zero allowed (produces infinity as expected)
  • Code compiles without errors
  • Original reproduction case still fails as expected (fix needs full build to test)

Next steps: Full build and integration testing will validate that the fix resolves the original crashing issue.

Fixes #16998.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: justinchuby <11205048+justinchuby@users.noreply.github.com>
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

You can commit the suggested changes from lintrunner.

Comment on lines +634 to +639
const size_t size = static_cast<size_t>(denominator_tensor.Shape().Size());

for (size_t i = 0; i < size; ++i) {
if (data[i] == T{0}) {
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
"Division by zero error in Div operator");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const size_t size = static_cast<size_t>(denominator_tensor.Shape().Size());
for (size_t i = 0; i < size; ++i) {
if (data[i] == T{0}) {
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
"Division by zero error in Div operator");
const size_t size = static_cast<size_t>(denominator_tensor.Shape().Size());
for (size_t i = 0; i < size; ++i) {
if (data[i] == T{0}) {
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
"Division by zero error in Div operator");

Comment on lines +649 to 654
const auto& input_tensor_1 = context->RequiredInput<Tensor>(1);

// Check for division by zero (only for integer types)
ORT_RETURN_IF_ERROR(CheckDivisionByZero<T>(input_tensor_1));

ProcessBroadcastSpanFuncs funcs{
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const auto& input_tensor_1 = context->RequiredInput<Tensor>(1);
// Check for division by zero (only for integer types)
ORT_RETURN_IF_ERROR(CheckDivisionByZero<T>(input_tensor_1));
ProcessBroadcastSpanFuncs funcs{
const auto& input_tensor_1 = context->RequiredInput<Tensor>(1);
// Check for division by zero (only for integer types)
ORT_RETURN_IF_ERROR(CheckDivisionByZero<T>(input_tensor_1));
ProcessBroadcastSpanFuncs funcs{

Comment on lines +967 to +972
test.AddInput<int32_t>("B", {1}, {0});
test.AddOutput<int32_t>("C", {1}, {0}); // Output doesn't matter since we expect failure

// Should return an error instead of crashing
test.Run(OpTester::ExpectResult::kExpectFailure,
"Division by zero error in Div operator");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
test.AddInput<int32_t>("B", {1}, {0});
test.AddOutput<int32_t>("C", {1}, {0}); // Output doesn't matter since we expect failure
// Should return an error instead of crashing
test.Run(OpTester::ExpectResult::kExpectFailure,
"Division by zero error in Div operator");
test.AddInput<int32_t>("B", {1}, {0});
test.AddOutput<int32_t>("C", {1}, {0}); // Output doesn't matter since we expect failure
// Should return an error instead of crashing
test.Run(OpTester::ExpectResult::kExpectFailure,
"Division by zero error in Div operator");

Comment on lines +978 to +983
test.AddInput<int64_t>("B", {1}, {0});
test.AddOutput<int64_t>("C", {1}, {0}); // Output doesn't matter since we expect failure

// Should return an error instead of crashing
test.Run(OpTester::ExpectResult::kExpectFailure,
"Division by zero error in Div operator");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
test.AddInput<int64_t>("B", {1}, {0});
test.AddOutput<int64_t>("C", {1}, {0}); // Output doesn't matter since we expect failure
// Should return an error instead of crashing
test.Run(OpTester::ExpectResult::kExpectFailure,
"Division by zero error in Div operator");
test.AddInput<int64_t>("B", {1}, {0});
test.AddOutput<int64_t>("C", {1}, {0}); // Output doesn't matter since we expect failure
// Should return an error instead of crashing
test.Run(OpTester::ExpectResult::kExpectFailure,
"Division by zero error in Div operator");

Comment on lines +991 to +993
test.AddOutput<float>("C", {1}, {std::numeric_limits<float>::infinity()});

// Should succeed and produce infinity
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
test.AddOutput<float>("C", {1}, {std::numeric_limits<float>::infinity()});
// Should succeed and produce infinity
test.AddOutput<float>("C", {1}, {std::numeric_limits<float>::infinity()});
// Should succeed and produce infinity

Comment on lines +1001 to +1003
test.AddOutput<double>("C", {1}, {std::numeric_limits<double>::infinity()});

// Should succeed and produce infinity
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
test.AddOutput<double>("C", {1}, {std::numeric_limits<double>::infinity()});
// Should succeed and produce infinity
test.AddOutput<double>("C", {1}, {std::numeric_limits<double>::infinity()});
// Should succeed and produce infinity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ORT aborts with the linspace implementation when input is empty
2 participants