YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
WARNING: SECURITY RESEARCH - PROOF OF CONCEPT ONLY
This repository contains malformed/crafted Circle (FlatBuffers) model files that trigger memory-safety crashes (out-of-bounds reads) in Samsung ONE's CircleImport.cpp loader. These are passive data files, not executable code β they do nothing on their own and only cause a crash when parsed by a vulnerable version of the Circle model loader.
DO NOT load these files with a production Circle/ONE runtime outside of an isolated, disposable research environment.
Findings Summary
| File | Finding | CWE | Confirmation | Runtime Location |
|---|---|---|---|---|
| tensor_index_fuzz_poc.circle | Tensor index OOB β subgraph.tensors[input_num] via op->inputs()[i] |
CWE-129 | β Fuzz-confirmed (3 crashes) | CircleImport.cpp:855, :918, :936 |
| buffer_opcode_manual_poc.circle | Buffer index OOB β buffers[const_tensor.buffer]->data |
CWE-129 | β Manual-confirmed | CircleImport.cpp:875 |
| buffer_opcode_manual_poc.circle | Opcode index OOB β operator_codes[opcode_index] passed to ConvertSubgraph |
CWE-129 | β Manual-confirmed | CircleImport.cpp:1059 |
| redzone_read_poc.circle | FlatBuffers relative offset reads past buffer end (ASan redzone) | CWE-125 | β Fuzz-confirmed | operator field accessor β op->inputs() |
Reproduction
- Build Samsung ONE's
circle-mlirtoolchain with AddressSanitizer enabled - Load each
.circlefile through the standard model import path (CircleImport) - Each file passes
VerifyModelBuffer()successfully but triggers an ASan-detected out-of-bounds read at the source locations listed above
All PoC files are structurally valid FlatBuffers β they pass the FlatBuffers verifier's structural checks. The vulnerability is that the verifier does NOT validate semantic consistency:
- Tensor indices are not checked against
tensors.size() - Buffer indices are not checked against
buffers.size() - Opcode indices are not checked against
operator_codes.size()
Root Cause
Samsung ONE's CircleImport.cpp uses unchecked std::vector::operator[] (or FlatBuffers Vector::Get()) to access tensors, buffers, and operator codes by their index, without verifying that the index is within bounds. The FlatBuffers verifier only ensures structural validity of the FlatBuffer fields, not that index values are valid references.
// CircleImport.cpp:855 β TENSOR INDEX OOB
auto &const_tensor = *subgraph.tensors[input_num]; // input_num from op->inputs()
// CircleImport.cpp:875 β BUFFER INDEX OOB
buffer = buffers[const_tensor.buffer]->data; // tensor.buffer from FlatBuffer
// CircleImport.cpp:1059 β OPCODE INDEX OOB
auto func_or_error = ConvertSubgraph(..., model->operator_codes, ...);
// Inside ConvertSubgraph: opcodes[op->opcode_index] is used unchecked
Mitigation
Add bounds checks before array accesses in CircleImport.cpp:
if (input_num < 0 || input_num >= subgraph.tensors.size()) { /* error */ return; }
if (const_tensor.buffer >= buffers.size()) { /* error */ return; }
if (opcode_index >= operator_codes.size()) { /* error */ return; }
Alternatively, replace operator[] with .at() which throws std::out_of_range.
Files
tensor_index_fuzz_poc.circle(670 bytes) β verified by libFuzzer + ASan; triggers heap-buffer-overflow at tensor index accessbuffer_opcode_manual_poc.circle(524 bytes) β manually crafted withtensor.buffer=999andopcode_index=999redzone_read_poc.circle(670 bytes) β fuzz-discovered; triggers SEGV via FlatBuffers offset past buffer endreport.mdβ Full vulnerability report
Credits
Discovered by Onurcan Genc via coverage-guided fuzzing with libFuzzer + ASan + UBSan.