Skip to content

Commit c9f6df1

Browse files
authored
Prevent signed integer overflow in pixel_shuffle size calculation (#16138)
Summary: The size calculation in `get_pixel_shuffle_out_target_size` can trigger signed integer overflow (UB) with very large upscale_factors. This manifested as an integer division by zero fault during fuzzing. Specifically, the calculation of `upscale_factor * upscale_factor` ([source](https://github.com/pytorch/executorch/blob/04f1e4d22383ffcbc770acf5002348e3f95082a2/kernels/portable/cpu/util/copy_ops_util.cpp#L364)) can overflow. In the motivating case, SizesType is a signed 32-bit integer and upscale_factor = 2^17. Since this is an impractically large upscale factor, I'm just adding a constraint that upscale_factor < 32768 (2^15). In theory, SizesType could be defined as less than 32 bits, but this seems unlikely in practice. I check this upper bound in `check_pixel_shuffle_args` and also assert in `get_pixel_shuffle_out_target_size` to ensure we don't hit UB. Differential Revision: D88693324
1 parent f26f228 commit c9f6df1

File tree

3 files changed

+14
-4
lines changed

3 files changed

+14
-4
lines changed

kernels/portable/cpu/op_pixel_shuffle.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,12 @@ Tensor& pixel_shuffle_out(
8484
ET_KERNEL_CHECK(ctx, tensor_is_default_dim_order(in), InvalidArgument, out);
8585
Tensor::SizesType expected_out_size[kTensorDimensionLimit];
8686
size_t expected_out_dim = 0;
87-
get_pixel_shuffle_out_target_size(
88-
in, upscale_factor, expected_out_size, &expected_out_dim);
87+
ET_KERNEL_CHECK(
88+
ctx,
89+
get_pixel_shuffle_out_target_size(
90+
in, upscale_factor, expected_out_size, &expected_out_dim),
91+
InvalidArgument,
92+
out);
8993

9094
// Make sure the output tensor is the right size.
9195
ET_KERNEL_CHECK(

kernels/portable/cpu/util/copy_ops_util.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,11 +346,15 @@ bool check_pixel_unshuffle_args(
346346
return true;
347347
}
348348

349-
void get_pixel_shuffle_out_target_size(
349+
bool get_pixel_shuffle_out_target_size(
350350
const Tensor& in,
351351
int64_t upscale_factor,
352352
executorch::aten::SizesType* out_sizes,
353353
size_t* out_ndim) {
354+
// Prevent signed integer overflow when computing upscale_factor ^ 2.
355+
ET_CHECK_OR_RETURN_FALSE(
356+
upscale_factor < 32768, "Upscale factor must be less than 32768.");
357+
354358
*out_ndim = in.dim();
355359
const executorch::aten::SizesType casted_upscale_factor = upscale_factor;
356360

@@ -366,6 +370,8 @@ void get_pixel_shuffle_out_target_size(
366370
out_sizes[i] = in.size(i) * casted_upscale_factor;
367371
i++;
368372
out_sizes[i] = in.size(i) * casted_upscale_factor;
373+
374+
return true;
369375
}
370376

371377
void get_pixel_unshuffle_out_target_size(

kernels/portable/cpu/util/copy_ops_util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ bool check_pixel_shuffle_args(
139139
int64_t upscale_factor,
140140
Tensor& out);
141141

142-
void get_pixel_shuffle_out_target_size(
142+
bool get_pixel_shuffle_out_target_size(
143143
const Tensor& in,
144144
int64_t upscale_factor,
145145
executorch::aten::SizesType* out_sizes,

0 commit comments

Comments
 (0)