YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
Arm NN ONNX pooling short kernel_shape heap over-read
Status: reproduced 3/3 with AddressSanitizer; final prior-art gate open.
Arm NN's ONNX parser requires the pooling kernel_shape attribute to exist,
but does not require it to contain the two spatial dimensions that
AddPoolingLayer() reads. A checker-valid ONNX model with a one-element
kernel_shape makes the parser read four bytes immediately beyond the
attribute vector during model loading.
Tested against Arm NN commit
2b61cecc9df7a43fca1463795062cf359e6be820.
Root cause
ReadMandatoryNodeUint32ListAttribute() returns the model-controlled attribute
as a vector. AddPoolingLayer() indexes elements zero and one without checking
the vector length:
std::vector<uint32_t> kernel_shape =
ReadMandatoryNodeUint32ListAttribute(node, "kernel_shape");
...
desc.m_PoolWidth = kernel_shape[1];
desc.m_PoolHeight = kernel_shape[0];
Affected source:
Differential proof
Both files pass onnx.checker.check_model() with ONNX 1.18.0.
| Artifact | kernel_shape |
Size | Arm NN result |
|---|---|---|---|
control-two-element-kernel-shape.onnx |
[2, 2] |
214 bytes | parses; exit 0 |
trigger-one-element-kernel-shape.onnx |
[2] |
212 bytes | ASan heap-buffer-overflow read; exit 134 |
Three independent trigger executions produced the same ASan classification, read size, allocation boundary, and parser frame. Three interleaved control executions parsed successfully.
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 4
#0 OnnxParserImpl::AddPoolingLayer
0 bytes after 4-byte region
SUMMARY: AddressSanitizer: heap-buffer-overflow
SHA-256:
1b70091779a90c7a2595a178c1bae5531348fa71c327d0970d1488160d8992a4 control-two-element-kernel-shape.onnx
0dd62b3ad68f03e43f1e4fcf2c7f1f91e53aff2f1ca81426b7babbb6e54de054 trigger-one-element-kernel-shape.onnx
Reproduce
Build current Arm NN with its ONNX parser and
-fsanitize=address,undefined -fno-omit-frame-pointer. Compile harness.cpp
against libarmnnOnnxParser, libarmnn, and the same protobuf library.
python3 generate_models.py
ASAN_OPTIONS=abort_on_error=1:detect_leaks=0 \
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
./harness models/control-two-element-kernel-shape.onnx
ASAN_OPTIONS=abort_on_error=1:detect_leaks=0 \
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
./harness models/trigger-one-element-kernel-shape.onnx
Impact
An application that loads an untrusted .onnx model through Arm NN's public
parser API can suffer a native out-of-bounds read before inference. The
demonstrated impact is deterministic denial of service. This report does not
claim disclosure of the adjacent bytes or code execution.
AddPoolingLayer() is shared by AveragePool and MaxPool, so the same
missing validation affects both operator paths.
Suggested remediation
Before indexing pooling attributes, require:
kernel_shape.size() == 2;strides.empty() || strides.size() == 2;pads.empty() || pads.size() == 4.
Reject other lengths with ParseException. Add regression tests for zero- and
one-element kernel_shape, one-element strides, and one- through
three-element pads.
Novelty
The final exact scan returned zero Hugging Face, Arm NN GitHub, or local
matches for AddPoolingLayer, kernel_shape[1], the ASan class, or the
affected line. Manual issue and pull-request searches likewise returned zero.
Adjacent public Arm NN findings affect the native FlatBuffer deserializer, TFLite auxiliary tensors, or generic tensor-shape multiplication. None validates the ONNX pooling attribute lengths or repairs this function.