Skip to content

Commit 469e4d5

Browse files
psiddhfacebook-github-bot
authored andcommitted
Fix heap-buffer-overflow in constant_pad_nd with overflow-safe bounds checking (pytorch#16468)
Summary: Fix fuzzer-discovered heap-buffer-overflow (T250636018) in the constant_pad_nd kernel. The bounds checking was missing the actual output buffer end pointer and used arithmetic that could overflow with crafted inputs. This adds proper out_data_end tracking and rewrites the bounds checks to use overflow-safe division instead of potentially-overflowing multiplication. Reviewed By: manuelcandales Differential Revision: D90188241
1 parent b031287 commit 469e4d5

1 file changed

Lines changed: 20 additions & 10 deletions

File tree

kernels/portable/cpu/op_constant_pad_nd.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void apply_padding_to_dim(
3636
IntArrayRef self_sizes,
3737
IntArrayRef self_strides,
3838
CTYPE* out_data,
39+
CTYPE* out_data_end,
3940
IntArrayRef out_sizes,
4041
IntArrayRef out_strides,
4142
IntArrayRef pad,
@@ -59,14 +60,12 @@ void apply_padding_to_dim(
5960
size_t in_step_len = self_strides[dim];
6061

6162
// Do not copy padding beyond the out tensor bounds.
63+
// Use division to avoid potential overflow in multiplication.
6264
if (pad_before > 0) {
63-
size_t numel = 1;
64-
for (ET_UNUSED const auto i : c10::irange(out_sizes.size())) {
65-
numel *= out_sizes[i];
66-
}
65+
size_t remaining = out_data_end - out_data;
6766
ET_KERNEL_CHECK_MSG(
6867
ctx,
69-
numel >= pad_before * out_step_len,
68+
out_step_len > 0 && remaining / out_step_len >= pad_before,
7069
InvalidArgument,
7170
/* void */,
7271
"Out tensor is too small for the requested padding.");
@@ -92,6 +91,15 @@ void apply_padding_to_dim(
9291
InvalidArgument,
9392
/* void */,
9493
"Out tensor overlaps with the input tensor. This is not supported.");
94+
// Bounds check before memcpy
95+
// Use overflow-safe check for remaining >= copy_len
96+
size_t remaining = out_data_end - out_data;
97+
ET_KERNEL_CHECK_MSG(
98+
ctx,
99+
remaining >= copy_len,
100+
InvalidArgument,
101+
/* void */,
102+
"Out tensor is too small for the copy operation.");
95103
memcpy(out_data, self_data, copy_nbytes);
96104
out_data += copy_len;
97105
self_data += copy_len;
@@ -107,6 +115,7 @@ void apply_padding_to_dim(
107115
self_sizes,
108116
self_strides,
109117
out_data,
118+
out_data_end,
110119
out_sizes,
111120
out_strides,
112121
pad,
@@ -120,14 +129,12 @@ void apply_padding_to_dim(
120129
}
121130

122131
// Do not copy padding beyond the out tensor bounds.
132+
// Use division to avoid potential overflow in multiplication.
123133
if (pad_after > 0) {
124-
size_t numel = 1;
125-
for (ET_UNUSED const auto i : c10::irange(out_sizes.size())) {
126-
numel *= out_sizes[i];
127-
}
134+
size_t remaining = out_data_end - out_data;
128135
ET_KERNEL_CHECK_MSG(
129136
ctx,
130-
numel >= pad_after * out_step_len,
137+
out_step_len > 0 && remaining / out_step_len >= pad_after,
131138
InvalidArgument,
132139
/* void */,
133140
"Out tensor is too small for the requested padding.");
@@ -182,13 +189,16 @@ void constant_pad_nd_out_impl(
182189
IntArrayRef out_sizes_ref(out_sizes, ndim);
183190
IntArrayRef out_strides_ref(out_strides, ndim);
184191

192+
CTYPE* out_data_end = out_data + out.numel();
193+
185194
apply_padding_to_dim(
186195
ctx,
187196
ndim,
188197
self_data,
189198
self_sizes_ref,
190199
self_strides_ref,
191200
out_data,
201+
out_data_end,
192202
out_sizes_ref,
193203
out_strides_ref,
194204
pad,

0 commit comments

Comments
 (0)