Skip to content

Commit 99ad89d

Browse files
bmehta001Copilot
andcommitted
Validate negative output dimensions in Pad and Slice operators
Add checks that output dimensions are not negative after computing them from user-supplied pads/slices. Without these checks, excessive negative padding or slicing could produce tensors with negative dimensions, leading to buffer underflows or undefined behavior. Zero-sized dimensions are valid (empty tensors) and are not rejected. Affected operators and providers: - CPU Pad: both reshaped and true output dimensions - CUDA Pad: output dimensions in compute loop - WebGPU Pad: output dimensions in compute loop - WebGPU Slice: output dimensions after ceil computation - JS onnxjs Slice (WebGL): output shape after ends - starts - JS onnxjs padShape utility - JS jsep padShape utility - JS jsep Slice (WebGPU): output shape after ceil computation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 47d5201 commit 99ad89d

8 files changed

Lines changed: 43 additions & 2 deletions

File tree

js/web/lib/onnxjs/backends/webgl/ops/slice.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ const createSliceProgramInfo = (
7070
const sliceOps: string[] = [];
7171
for (let i = 0; i < normalizedAxes.length; i++) {
7272
outputShape[normalizedAxes[i]] = ends[i] - starts[i];
73+
if (outputShape[normalizedAxes[i]] < 0) {
74+
throw new Error(
75+
`Output dimension ${normalizedAxes[i]} is negative (${outputShape[normalizedAxes[i]]}). This may occur from excessive negative slicing.`,
76+
);
77+
}
7378
if (starts[i] > 0) {
7479
sliceOps.push(`outputIdx[${normalizedAxes[i]}] += ${starts[i]};`);
7580
} // else { sliceOps.push(`outputIdx[${normalizedAxes[i]}] += 0;`); }

js/web/lib/onnxjs/util.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,15 @@ export class ShapeUtil {
741741
*/
742742
static padShape(dims: readonly number[], pad: readonly number[]): readonly number[] {
743743
const rank = dims.length;
744-
return dims.map((v, i) => v + pad[i] + pad[i + rank]);
744+
return dims.map((v, i) => {
745+
const nextDim = v + pad[i] + pad[i + rank];
746+
if (nextDim < 0) {
747+
throw new Error(
748+
`Output dimension ${i} is negative (${nextDim}). This may occur from excessive negative padding.`,
749+
);
750+
}
751+
return nextDim;
752+
});
745753
}
746754

747755
/**

js/web/lib/wasm/jsep/util.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,15 @@ export class ShapeUtil {
222222
*/
223223
static padShape(dims: readonly number[], pad: readonly number[]): readonly number[] {
224224
const rank = dims.length;
225-
return dims.map((v, i) => v + pad[i] + pad[i + rank]);
225+
return dims.map((v, i) => {
226+
const nextDim = v + pad[i] + pad[i + rank];
227+
if (nextDim < 0) {
228+
throw new Error(
229+
`Output dimension ${i} is negative (${nextDim}). This may occur from excessive negative padding.`,
230+
);
231+
}
232+
return nextDim;
233+
});
226234
}
227235

228236
/**

js/web/lib/wasm/jsep/webgpu/ops/slice.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ const createSliceProgramInfo = (inputs: readonly TensorView[], attributes: Slice
166166
const outputShape = inputShape.slice(0);
167167
axes.forEach((axis, _) => {
168168
outputShape[axis] = Math.ceil((ends[axis] - starts[axis]) / steps[axis]);
169+
if (outputShape[axis] < 0) {
170+
throw new Error(
171+
`Output dimension ${axis} is negative (${outputShape[axis]}). This may occur from excessive negative slicing.`,
172+
);
173+
}
169174
});
170175
const outputTensorInfo: TensorInfo = { dims: outputShape, dataType: inputs[0].dataType };
171176

onnxruntime/core/providers/cpu/tensor/pad.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,11 +457,17 @@ static Status PadImpl(OpKernelContext* ctx,
457457
effective_input_extents.push_back(extent);
458458
reshaped_output_dims[i] += SafeInt<int64_t>(reshaped_pad[i]) + reshaped_pad[i + new_dims_count] +
459459
reshaped_slice[i] + reshaped_slice[i + new_dims_count];
460+
ORT_RETURN_IF(reshaped_output_dims[i] < 0,
461+
"Output dimension ", i, " is negative (", reshaped_output_dims[i],
462+
"). This may occur from excessive negative padding/slicing.");
460463
}
461464

462465
// Compute true output dimensions
463466
for (size_t i = 0; i < data_rank; i++) {
464467
output_dims[i] += SafeInt<int64_t>(pads[i]) + pads[i + data_rank] + slices[i] + slices[i + data_rank];
468+
ORT_RETURN_IF(output_dims[i] < 0,
469+
"Output dimension ", i, " is negative (", output_dims[i],
470+
"). This may occur from excessive negative padding/slicing.");
465471
}
466472

467473
// If the input is empty, but output shape may not be, need padding only

onnxruntime/core/providers/cuda/tensor/pad.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ Status Pad<T>::ComputeInternal(OpKernelContext* ctx) const {
250250
lower_pads[i] = SafeInt<int64_t>((*p_pads)[i]) + (*p_slices)[i];
251251
upper_pads[i] = SafeInt<int64_t>((*p_pads)[i + dimension_count]) + (*p_slices)[i + dimension_count];
252252
output_dims[i] += SafeInt<int64_t>(lower_pads[i]) + upper_pads[i];
253+
ORT_RETURN_IF(output_dims[i] < 0,
254+
"Output dimension ", i, " is negative (", output_dims[i],
255+
"). This may occur from excessive negative padding/slicing.");
253256
}
254257

255258
TensorShapeVector effective_input_extents;

onnxruntime/core/providers/webgpu/tensor/pad.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ Status Pad::ComputeInternal(ComputeContext& context) const {
6868
int64_t upper_pad = (*p_pads)[i + dimension_count] + (*p_slices)[i + dimension_count];
6969
lower_pads[i] = static_cast<int32_t>(lower_pad);
7070
output_dims[i] += lower_pad + upper_pad;
71+
ORT_RETURN_IF(output_dims[i] < 0,
72+
"Output dimension ", i, " is negative (", output_dims[i],
73+
"). This may occur from excessive negative padding/slicing.");
7174
}
7275
TensorShape output_shape(output_dims);
7376

onnxruntime/core/providers/webgpu/tensor/slice.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ Status Slice::ComputeInternal(ComputeContext& context) const {
206206
}
207207
auto temp = static_cast<int64_t>(ceil(1.0 * (end - start) / static_cast<float>(step)));
208208
output_dims[axes[i]] = (temp > 0 && dim_value != 0) ? temp : 0;
209+
ORT_RETURN_IF(output_dims[axes[i]] < 0,
210+
"Output dimension ", axes[i], " is negative (", output_dims[axes[i]],
211+
"). This may occur from excessive negative slicing.");
209212
}
210213

211214
// insert missing dimensions

0 commit comments

Comments
 (0)