Skip to content

ConvTransposeWithDynamicPads msrc116345#28548

Closed
yuslepukhin wants to merge 4 commits into
mainfrom
yuslepukhin/conv_transpose_msrc116345
Closed

ConvTransposeWithDynamicPads msrc116345#28548
yuslepukhin wants to merge 4 commits into
mainfrom
yuslepukhin/conv_transpose_msrc116345

Conversation

@yuslepukhin
Copy link
Copy Markdown
Member

This pull request strengthens input validation and error handling for the ConvTranspose operator (including dynamic pads) across both CPU and CUDA providers, and in shape inference logic. The main improvements ensure that invalid or inconsistent input shapes, attributes, and parameters are caught early with clear error messages, improving robustness and compliance with the ONNX specification.

Input shape and attribute validation:

  • Added checks to ensure input tensor X and filter tensor W have at least 2 dimensions, and that the group attribute is positive in both the shape inference and kernel implementations. [1] [2] [3]
  • Enhanced validation for the dynamic pads input: ensures it is present, is a 1D tensor, has the correct size, and contains only non-negative values. [1] [2]

Parameter validation (stride, dilation, output padding):

  • Added checks to ensure that output_padding is less than either the stride or dilation for each spatial dimension, as required by the ONNX spec. [1] [2]
  • Enforced that spatial dimension sizes, stride, kernel size, and dilation are all positive, and output padding is non-negative, in shape calculation routines.

Shape inference and calculation improvements:

  • Improved error messages during shape inference when output shape values are inconsistent with input shape.
  • Used SafeInt for safer arithmetic in output shape calculations to prevent overflow.

General code maintenance:

  • Included necessary headers for SafeInt where used. [1] [2]

Testing:

  • Added a basic functional test for 2D ConvTranspose with dynamic pads.

** References:
onnx/onnx#7997
#28524

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR strengthens ConvTransposeWithDynamicPads validation across shape inference and CPU/CUDA execution paths, with added regression and functional tests for invalid shapes, dynamic pads, and output padding constraints.

Changes:

  • Adds rank, dynamic pads, output padding, and arithmetic validation in CPU/CUDA ConvTranspose paths.
  • Tightens ConvTransposeWithDynamicPads shape inference errors.
  • Expands contrib op tests for dynamic pads and invalid inputs.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
onnxruntime/core/graph/contrib_ops/contrib_defs.cc Updates ConvTransposeWithDynamicPads shape inference validation and messages.
onnxruntime/core/providers/cpu/nn/conv_transpose_attributes.h Adds runtime validation and SafeInt arithmetic for CPU/shared ConvTranspose attribute handling.
onnxruntime/core/providers/cuda/nn/conv_transpose.cc Mirrors validation in CUDA ConvTranspose state setup.
onnxruntime/test/contrib_ops/conv_transpose_with_dynamic_pads_test.cc Adds functional and failure tests for dynamic pads and ConvTranspose edge cases.
Comments suppressed due to low confidence (1)

onnxruntime/test/contrib_ops/conv_transpose_with_dynamic_pads_test.cc:139

  • This test expects the shape-inference error text, but Pads is added as a runtime input because AddInput's initializer flag is not set. The kernel path reports "Pads input must be a 1D tensor...", so the expected substring with lowercase quoted 'pads' will not match. Make Pads an initializer here or update the expected error text.
  test.AddInput<int64_t>("Pads", {2, 2}, std::vector<int64_t>{0, 0, 0, 0});  // 2D instead of 1D
  test.AddOutput<float>("Y", {1, 1, 5, 5}, std::vector<float>(25, 0.0f));

  test.Run(OpTester::ExpectResult::kExpectFailure, "'pads' input must be a 1D");

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread onnxruntime/core/providers/cpu/nn/conv_transpose_attributes.h
Comment thread onnxruntime/core/providers/cuda/nn/conv_transpose.cc
Comment thread onnxruntime/core/providers/cuda/nn/conv_transpose.cc
Comment thread onnxruntime/test/contrib_ops/conv_transpose_with_dynamic_pads_test.cc Outdated
Comment thread onnxruntime/test/contrib_ops/conv_transpose_with_dynamic_pads_test.cc Outdated
Comment thread onnxruntime/test/contrib_ops/conv_transpose_with_dynamic_pads_test.cc Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (2)

onnxruntime/core/providers/cuda/nn/conv_transpose.cc:361

  • This now treats Pads as required at runtime, but the ConvTransposeWithDynamicPads schema still declares input 2 as OpSchema::Optional (contrib_defs.cc:1730). Either the schema should be tightened to make Pads required, or the kernel should define behavior for an omitted Pads input; otherwise model validation can accept a graph that this kernel rejects as missing a required input.
      if (Pads == nullptr) {
        return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
                               "Pads input is required for dynamic padding mode.");

onnxruntime/core/providers/cpu/nn/conv_transpose_attributes.h:276

  • These new validations use ORT_ENFORCE inside a helper that is reached from PrepareForCompute; in ORT_NO_EXCEPTIONS builds ORT_ENFORCE aborts rather than returning a failure Status (see common.h:98-142). For user-controlled cases like negative output_padding, this can terminate the process instead of producing the INVALID_ARGUMENT status used by the other new checks. Please return/propagate Status from this helper or validate these conditions before calling it.
    ORT_ENFORCE(in_size > 0, "Input spatial dimension must be positive. Got: ", in_size);
    ORT_ENFORCE(stride > 0, "Stride must be positive. Got: ", stride);
    ORT_ENFORCE(kernel > 0, "Kernel size must be positive. Got: ", kernel);
    ORT_ENFORCE(dilation > 0, "Dilation must be positive. Got: ", dilation);
    ORT_ENFORCE(adj >= 0, "Output padding must be non-negative. Got: ", adj);

Comment on lines +111 to +114
// Security: Pads tensor with wrong number of elements should fail.
// When Pads is available as initializer, shape inference catches this with fail_shape_inference.
// When Pads is only available at runtime, kernel validation catches it.
TEST(ContribOpTest, ConvTransposeWithDynamicPads_InvalidPadsSize) {
Comment on lines +59 to +60
if (group <= 0) {
fail_shape_inference("group must be positive");
Comment on lines +140 to +160
if (Pads == nullptr) {
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
"Pads input is required for dynamic padding mode.");
}
if (Pads->Shape().NumDimensions() != 1) {
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
"Pads input must be a 1D tensor. Got rank: ", Pads->Shape().NumDimensions());
}
const int64_t expected_pads_size = SafeInt<int64_t>(kernel_shape.size()) * 2;
if (Pads->Shape()[0] != expected_pads_size) {
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
"Pads input must have ", expected_pads_size, " elements (2 * num_spatial_dims). Got: ",
Pads->Shape()[0]);
}
for (int64_t i = 0; i < Pads->Shape()[0]; ++i) {
const int64_t pad_val = Pads->Data<int64_t>()[i];
if (pad_val < 0) {
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
"Pad values must be non-negative. Got: ", pad_val, " at index ", i);
}
local_pads.push_back(pad_val);
Comment on lines +276 to +278
// When dynamic_padding is enabled, Pads may change between calls even if X/W
// shapes are unchanged, so we must always recompute the output shape.
if (input_dims_changed || w_dims_changed || dynamic_padding) {
@yuslepukhin
Copy link
Copy Markdown
Member Author

Merging to #28524 and closing.

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.

2 participants