YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
PoC: stack buffer overflow in ExecuTorch unfold_copy via a 16-dim tensor (CWE-121/787)
Executing a crafted ExecuTorch program (.pte) that applies unfold to a tensor with exactly 16
dimensions overflows a fixed-size stack array in the unfold_copy kernel.
Root cause
kernels/portable/cpu/op_unfold_copy.cpp:30:Tensor::SizesType expected_output_size[kTensorDimensionLimit];โ a 16-element stack array (kTensorDimensionLimit = 16, valid indices 0..15).kernels/portable/cpu/util/copy_ops_util.cppget_unfold_copy_out_target_size:
for (auto i : c10::irange(self.dim())) out_sizes[i] = self.size(i); // out_sizes[0..self.dim()-1]
out_sizes[dim] = (self.size(dim) - size + step) / step; // dim < self.dim(): in bounds
out_sizes[self.dim()] = size; // <-- writes index self.dim()
*out_ndim = self.dim() + 1; // output is self.dim()+1 dims
unfold produces a self.dim()+1-dimensional output, but the size buffer is allocated at exactly
kTensorDimensionLimit (16) elements. The .pte loader admits 16-dimension tensors โ
runtime/executor/tensor_parser_portable.cpp:67 checks dim <= kTensorDimensionLimit (non-strict), and
check_unfold_copy_args validates only the unfold dim parameter (< self.dim()), never that
self.dim() < kTensorDimensionLimit. So a crafted .pte whose unfold input has 16 dimensions makes
out_sizes[16] a write one element past the 16-element stack array โ stack OOB write at execution time.
Reproduce (AddressSanitizer)
g++ -fsanitize=address -g -O0 executorch_unfold_copy_stack_overflow_harness.cpp -o poc && ./poc
# expected_output_size[16]; self.dim()=16 (loader allows dim<=16) -> writes out_sizes[16]
# ==ERROR: AddressSanitizer: stack-buffer-overflow WRITE of size 4 ... overflows 'expected_output_size'
Affected
- Repository: pytorch/executorch (commit 55a71e6442cc78dc6cae6d68fea9b186f95a17cc)
Fix
Size expected_output_size at kTensorDimensionLimit + 1, or reject self.dim() >= kTensorDimensionLimit
in check_unfold_copy_args (unfold needs one extra output dimension).