ConvTransposeWithDynamicPads msrc116345#28548
Conversation
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
Padsas required at runtime, but the ConvTransposeWithDynamicPads schema still declares input 2 asOpSchema::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_ENFORCEinside a helper that is reached fromPrepareForCompute; in ORT_NO_EXCEPTIONS buildsORT_ENFORCEaborts rather than returning a failureStatus(seecommon.h:98-142). For user-controlled cases like negativeoutput_padding, this can terminate the process instead of producing the INVALID_ARGUMENT status used by the other new checks. Please return/propagateStatusfrom 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);
| // 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) { |
| if (group <= 0) { | ||
| fail_shape_inference("group must be positive"); |
| 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); |
| // 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) { |
|
Merging to #28524 and closing. |
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:
Xand filter tensorWhave at least 2 dimensions, and that thegroupattribute is positive in both the shape inference and kernel implementations. [1] [2] [3]Parameter validation (stride, dilation, output padding):
output_paddingis less than either the stride or dilation for each spatial dimension, as required by the ONNX spec. [1] [2]Shape inference and calculation improvements:
SafeIntfor safer arithmetic in output shape calculations to prevent overflow.General code maintenance:
SafeIntwhere used. [1] [2]Testing:
** References:
onnx/onnx#7997
#28524