Arm NN .armnn Deserializer Stack Buffer Overflow via TensorInfo.dimensionSpecificity
Summary
This repository contains a benign proof of concept for a schema-valid Arm NN
FlatBuffers model artifact that triggers a stack-buffer-overflow in the Arm NN
v26.01 .armnn deserializer.
The bug is reached while converting serialized TensorInfo data into Arm NN's
runtime TensorInfo. The deserializer allocates a fixed stack array:
bool dimensionsSpecificity[armnn::MaxNumOfTensorDimensions];
armnn::MaxNumOfTensorDimensions is 5, but the serialized
dimensionSpecificity vector length is copied without a bounds check:
auto dimensionSpecificity = tensorPtr->dimensionSpecificity();
size = dimensionSpecificity->size();
for (unsigned int i = 0; i < size; ++i)
{
dimensionsSpecificity[i] = dimensionSpecificity->Get(i);
}
A .armnn artifact can therefore provide more than 5 dimensionSpecificity
entries and write past the fixed stack array during deserialization.
The PoC is intentionally non-destructive. It contains no shell command, network callback, persistence, credential access, or payload beyond the model file fields needed to reach the parser bug.
Impact
- Artifact-carried native memory corruption during
.armnnmodel deserialization. - FlatBuffers verification accepts the artifact before the Arm NN loader reaches the vulnerable code path.
- A release loader segfaults on the main artifact.
- ASAN/UBSAN identifies a stack-buffer-overflow write in
armnnDeserializer::ToTensorInfo()atDeserializer.cpp:756. - ModelScan 0.8.8 reports zero issues because
.armnnis not scanned.
This is not a Python exception and not a malformed CLI invocation. The trigger is contained in the serialized model artifact.
Affected Version Tested
- Arm NN SDK
v26.01 - Local tested commit:
600c0004a2a7a2d600a3bce22ef83193de1dde57 - FlatBuffers
24.3.25 - ModelScan
0.8.8 - Linux x86_64 local build
The same unchecked loop was also observed in a local checkout of Arm NN
v25.11, but this repository's primary verification evidence is for v26.01.
Files
artifacts/dim_spec_len1024_oob_write_crash.armnn
Main PoC. FlatBuffers verifier accepts it; release loader segfaults; ASAN
reports a stack-buffer-overflow write.
artifacts/dim_spec_len6_oob_write.armnn
Minimal one-byte-overflow PoC. Useful for showing the smallest vector length
that crosses MaxNumOfTensorDimensions.
artifacts/dim_spec_len1024_oob_write_crash.json
JSON source for the main PoC artifact.
scripts/build_dim_specificity_stack_overflow.py
Generator used to create the PoC artifacts from Arm NN's FlatBuffers schema.
evidence/verification_summary.json
Captured local verifier, release-loader, control-loader, and ASAN outputs.
evidence/followup_notes_dim_specificity_stack_overflow.md
Additional notes, duplicate-check notes, and command summary.
evidence/sha256.txt
SHA256 hashes for uploaded artifacts and scripts.
Reproduction
The commands below assume a local Arm NN v26.01 build environment equivalent to
the one used during verification. The paths under /workspace/arm_nn_flatbuffers
refer to the local build tree used to produce the evidence files.
1. Confirm FlatBuffers Verifier Accepts the Artifact
/workspace/arm_nn_flatbuffers/lab/verify_armnn_flatbuffer \
artifacts/dim_spec_len1024_oob_write_crash.armnn
Expected output:
VERIFY_OK bytes=2484
2. Confirm a Valid Control Model Loads
/workspace/arm_nn_flatbuffers/lab/load_armnn \
/workspace/arm_nn_flatbuffers/lab/control_valid.armnn
Expected output:
LOAD_OK network=1
3. Trigger the Release Loader Crash
/workspace/arm_nn_flatbuffers/lab/load_armnn \
artifacts/dim_spec_len1024_oob_write_crash.armnn
Observed locally:
SIGSEGV
The captured verification summary records the release loader return code as
-11.
4. Trigger the ASAN/UBSAN Evidence
ASAN_OPTIONS=abort_on_error=0:symbolize=1:halt_on_error=1 \
/workspace/arm_nn_flatbuffers/lab/followup_armnn_dim_specificity/load_armnn_followup_asan \
artifacts/dim_spec_len1024_oob_write_crash.armnn
Observed locally:
runtime error: index 5 out of bounds for type 'bool [5]'
runtime error: store to address ... with insufficient space for an object of type 'bool'
ERROR: AddressSanitizer: stack-buffer-overflow
WRITE of size 1
#0 armnnDeserializer::ToTensorInfo(...) Deserializer.cpp:756
#1 armnnDeserializer::IDeserializer::DeserializerImpl::SetupInputLayers(...) Deserializer.cpp:1089
#2 armnnDeserializer::IDeserializer::DeserializerImpl::CreateNetworkFromGraph(...) Deserializer.cpp:939
#3 armnnDeserializer::IDeserializer::DeserializerImpl::CreateNetworkFromBinary(...) Deserializer.cpp:882
5. Scanner Behavior
/workspace/arm_nn_flatbuffers/.venv/bin/modelscan \
-p artifacts/dim_spec_len1024_oob_write_crash.armnn \
-r json --show-skipped
Observed locally:
{
"total_issues": 0,
"scanned": {"total_scanned": 0},
"skipped": {
"total_skipped": 1,
"skipped_files": [
{
"category": "SCAN_NOT_SUPPORTED",
"source": "dim_spec_len1024_oob_write_crash.armnn"
}
]
}
}
This is not claimed as a standalone scanner bypass; it is included to document that the dangerous artifact is not inspected by the scanner in this environment.
Root Cause Details
In Arm NN v26.01, include/armnn/Types.hpp defines:
constexpr unsigned int MaxNumOfTensorDimensions = 5U;
In src/armnnDeserializer/Deserializer.cpp, ToTensorInfo() allocates a
fixed-size stack buffer using that value:
bool dimensionsSpecificity[armnn::MaxNumOfTensorDimensions];
The deserializer then uses the serialized vector's length as the copy bound:
size = dimensionSpecificity->size();
for (unsigned int i = 0; i < size; ++i)
{
dimensionsSpecificity[i] = dimensionSpecificity->Get(i);
}
The artifact dim_spec_len1024_oob_write_crash.armnn sets
TensorInfo.dimensions to a normal one-dimensional tensor while setting
TensorInfo.dimensionSpecificity to a much longer boolean vector. The
FlatBuffers schema permits the vector, the FlatBuffers verifier accepts the
serialized file, and the Arm NN deserializer writes past the fixed stack array.
Hashes
a73e0e4350808d6c82ea8fe4066e02c638b00010c34539c4604a6720f122df36 artifacts/dim_spec_len1024_oob_write_crash.armnn
98c259b1abac9b138b68427d0b6b15e958bcd0a756dac485ce0377cef9017ef9 artifacts/dim_spec_len1024_oob_write_crash.json
990b49d7cfa3a977f7947d5d4c5724be8bc3e44aa84d82e1b3424666f4b51470 artifacts/dim_spec_len6_oob_write.armnn
098e6b9a788daaeac94c7d76d99ff03991880cde620c9c856561b344819e4ba3 scripts/build_dim_specificity_stack_overflow.py
Limitations
- This PoC demonstrates memory corruption and crash; it does not demonstrate code execution.
- Exploitability beyond controlled stack write/crash was not attempted.
- The ASAN binary used for verification is not uploaded because it is a large
local build artifact. The captured sanitizer output is included under
evidence/verification_summary.json. - ModelScan not supporting
.armnnis not itself the vulnerability; the vulnerability is the Arm NN native deserializer memory corruption.
Duplicate Check Notes
Searches were performed for Arm NN dimensionSpecificity,
ToTensorInfo, Deserializer.cpp, stack-buffer-overflow, and FlatBuffers
deserializer crash terms. No public matching advisory or issue was found during
local triage.
Checked source areas:
- Arm NN
v26.01src/armnnDeserializer/Deserializer.cpp - Arm NN
v26.01include/armnn/Types.hpp - Arm NN GitHub security/advisory pages