YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
PoC: stack buffer overflow in Samsung/ONE luci-interpreter StridedSlice kernel (CWE-121/787)
Loading + executing a crafted Circle model (.circle) with a StridedSlice op whose input tensor has rank
= 6 overflows fixed-size stack arrays in the luci-interpreter StridedSlice kernel.
Root cause
compiler/luci-interpreter/src/kernels/StridedSlice.cpp:
assert(input()->shape().num_dims() <= 5); // :47 (stripped in release / NDEBUG)
tflite::StridedSliceParams op_params{}; // stack; start_indices[5]/stop_indices[5]/strides[5]
for (int i = 0; i < input()->shape().num_dims(); i++) {// :66 bound = input rank (no cap)
op_params.start_indices[i] = getTensorData<int32_t>(begin())[i]; // :68 OOB for i>=5
op_params.stop_indices[i] = getTensorData<int32_t>(end())[i]; // :69
op_params.strides[i] = getTensorData<int32_t>(strides())[i]; // :70
}
tflite::StridedSliceParams (upstream tensorflow/lite/kernels/internal/types.h, included via
reference/strided_slice.h) has fixed int32_t start_indices[5]/stop_indices[5]/strides[5]. The kernel's
only rank guard is the assert(num_dims <= 5) at line 47, which release (NDEBUG) builds strip; the model
loader (loader/nodes/StridedSlice.cpp) does no rank validation (only assert(arity == 4)). A crafted
.circle whose StridedSlice input has rank >= 6 (with begin/end/strides of matching length) makes both
configure() (:66-71) and execute() (:115-120) write index 5+ into the size-5 stack arrays → stack OOB
write at inference time. Distinct from the filed importer bugs (negative subgraph index, CircleConst
num_elements), which are in luci/import, not the executor kernel. (The assert(<= 5) is the developer
acknowledging the [5] limit, and CMakeLists.txt suppresses -Wno-error=array-bounds for this unit.)
Reproduce (AddressSanitizer)
g++ -fsanitize=address -g -O0 circle_stridedslice_stack_overflow_harness.cpp -o poc && ./poc
# input rank (num_dims) = 6 (assert <= 5 stripped in release)
# configure() loops i in [0,6) writing start_indices[i]/stop_indices[i]/strides[i] ...
# ==ERROR: AddressSanitizer: stack-buffer-overflow WRITE of size 4 ... overflows 'start_indices'
Fix
Replace the assert with a hard runtime check that throws when input()->shape().num_dims() > 5 (the
StridedSliceParams capacity) before the loop, in both configure() and execute(), and/or validate rank in the
loader.