Views
No views yet
.armnn flatbuffer deserializer (armnnDeserializer), triggered when loading an untrusted model file.src/armnnDeserializer/Deserializer.cpp, function ToTensorInfo(). Class: CWE-787 out-of-bounds write / stack-buffer-overflow (memory corruption, ACE-plausible).ToTensorInfo() copies the attacker-controlled dimensionSpecificity boolean vector from the model into a fixed 5-element stack array bool dimensionsSpecificity[armnn::MaxNumOfTensorDimensions] (line 746) with no length check: size = dimensionSpecificity->size() (line 753, attacker-controlled) then for (i=0; i<size; ++i) dimensionsSpecificity[i] = dimensionSpecificity->Get(i) (line 756). A model whose dimensionSpecificity vector is longer than 5 overflows the stack buffer.dimensions and dimensionSpecificity are independent fields in the TensorInfo table; VerifyBuffer validates flatbuffer structure but caps neither length. The sibling shape APIs (TensorShape via CheckValidNumDimensions, PermutationVector ctor) do enforce the 5-element bound — this inline loop is the one place that omits it.poc_graph.armnn.base64 — the malicious model (base64 of a 356-byte .armnn), dimensionSpecificity = 128 booleans. Decode: base64 -d poc_graph.armnn.base64 > poc_graph.armnnpoc_benign.armnn.base64 — benign control (dimensionSpecificity = 1 boolean); parses cleanly (non-vacuous evidence).poc_graph.json / poc_benign.json — model sources; regenerate with flatc --binary src/armnnSerializer/ArmnnSchema.fbs poc_graph.json.asan_trace.txt — full AddressSanitizer report.- Reached from the public API `IDeserializer::CreateNetworkFromBinary(bytes)` -> CreateNetworkFromGraph -> SetupInputLayers (Deserializer.cpp:1089) -> ToTensorInfo -> OOB write at Deserializer.cpp:756. AddressSanitizer (Docker, reference backend, -fsanitize=address) reports `stack-buffer-overflow, WRITE of size 1` at ToTensorInfo Deserializer.cpp:756, overflowing `dimensionsSpecificity` [544,549) at offset 549 (the 6th element). The benign control parses with no crash, confirming the crash is caused by the oversized vector, not generic malformed input.
-
- ## Suggested fix
-
- Cap the copy at the array bound and reject, matching sibling behavior: after `size = dimensionSpecificity->size();`, add `if (size > armnn::MaxNumOfTensorDimensions) throw ParseException("dimensionSpecificity exceeds MaxNumOfTensorDimensions");`
-
- ## Honest scope
-
- Confirmed as a write primitive (ASAN WRITE), not weaponized to code execution. Written byte values are 0/1 (bool); the overflow length is fully attacker-controlled and smashes adjacent stack locals (a TensorShape and three TensorInfo objects constructed/used after the overflow) plus the saved frame — a controllable stack memory-corruption primitive.
- ]