Circle External Buffer Offset/Size OOB Read Candidate
Date: 2026-06-26
Target: Huntr model format circle ($1,500 lane)
Source snapshot:
- Repo:
research/triage/audits/circle-2026-06-26/ONE - Commit:
de7f4736dc4c4f5e47f72a4022a9aa9ac6d1ad1a - Last commit:
de7f4736 [exo] Fix exception throw for unknown dialect (#16483)
Verdict
Submission candidate.
I found a verifier-clean Circle file that causes an ASan heap-buffer-overflow in Samsung ONE's circledump path. The bug is an external-buffer bounds check gap: mio_circle::Reader::buffer_info() checks only offset with std::vector::at(), while attacker-controlled size is returned to callers without validating offset + size <= raw_file_size.
The strongest demonstrated sink is now the real circledump::dump_buffer() code path, compiled directly with the current generated Circle schema and ASan. A production runtime loader impact would still strengthen severity, but this is no longer just a Reader harness.
Bug Shape
Circle's schema permits buffers whose tensor data lives outside the FlatBuffer region:
- circle_schema.fbs
- Fields:
offset: ulong,size: ulong - Comment: offset is relative to the beginning of the file and valid if greater than
1.
The vulnerable reader path:
- Reader.cpp
buffer_info()setsbuff_data = &_rawdata->at(buffer_offset)at line 125.- It returns
buffer->size()at line 127. - It does not validate that the returned byte span is inside
_rawdata.
The known caller/sink:
- Dump.cpp
circledumpcallsreader.buffer_info(i, &buff_data, ext_offset)and thendump_buffer(os, buff_data, size, 16).dump_buffer()readsbuffer[i]for up to 16 bytes.
Artifacts
- PoC model: external_offset_oob.circle
- SHA256:
20962ae3e01d2489f1ba6766f4d804414e5e5cb490589a23aa986f97abe0abd5 - Size: 232 bytes
- External buffer:
offset=231,size=4096 - Generator: make_circle_external_oob.cpp
- Direct upstream Reader probe: circle_reader_external_oob_probe.cpp
- ASan stderr: asan-reader-oob.stderr.txt
- Direct
circledumpcore driver: circledump_direct_driver.cpp circledumpASan stderr: asan-circledump-direct.stderr.txt- MFV scan output:
/tmp/mfv-scan-circle-external-oob
Reproduction
Use FlatBuffers 23.5.26 headers because the generated Circle header asserts that version. I used /tmp/flatbuffers-23.5.26/include.
cd /home/bradd/.openclaw/workspace
clang++ -std=c++17 -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer \
-I/tmp/flatbuffers-23.5.26/include \
-Iresearch/triage/audits/circle-2026-06-26/ONE/onert-micro/externals/gen/circle-generated \
research/triage/audits/circle-2026-06-26/poc/make_circle_external_oob.cpp \
-o /tmp/make_circle_external_oob
/tmp/make_circle_external_oob \
research/triage/audits/circle-2026-06-26/poc/external_offset_oob.circle
rm -rf /tmp/circle-include
mkdir -p /tmp/circle-include/mio
ln -s /home/bradd/.openclaw/workspace/research/triage/audits/circle-2026-06-26/ONE/onert-micro/externals/gen/circle-generated/circle \
/tmp/circle-include/mio/circle
clang++ -std=c++17 -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer \
-I/tmp/flatbuffers-23.5.26/include \
-I/tmp/circle-include \
-Iresearch/triage/audits/circle-2026-06-26/ONE/compiler/mio-circle/include \
research/triage/audits/circle-2026-06-26/poc/circle_reader_external_oob_probe.cpp \
research/triage/audits/circle-2026-06-26/ONE/compiler/mio-circle/src/Reader.cpp \
research/triage/audits/circle-2026-06-26/ONE/compiler/mio-circle/src/Helper.cpp \
-o /tmp/circle_reader_external_oob_probe
ASAN_OPTIONS=abort_on_error=0:symbolize=1 \
/tmp/circle_reader_external_oob_probe \
research/triage/audits/circle-2026-06-26/poc/external_offset_oob.circle
Observed:
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 1
circle_reader_external_oob_probe.cpp:36
0 bytes after 232-byte region
Stronger circledump core reproduction:
cd /home/bradd/.openclaw/workspace
# Build FlatBuffers 23.5.26 flatc/libflatbuffers, then regenerate the current Circle schema.
cmake -S /tmp/flatbuffers-23.5.26 -B /tmp/flatbuffers-23.5.26-build \
-G Ninja -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_INSTALL=OFF -DCMAKE_BUILD_TYPE=Release
cmake --build /tmp/flatbuffers-23.5.26-build --target flatc flatbuffers -j2
rm -rf /tmp/circle-generated-current /tmp/circle-include-current
mkdir -p /tmp/circle-generated-current /tmp/circle-include-current/mio/circle /tmp/circle-generated-current/circle
/tmp/flatbuffers-23.5.26-build/flatc --cpp -o /tmp/circle-generated-current \
research/triage/audits/circle-2026-06-26/ONE/runtime/libs/circle-schema/circle_schema.fbs
ln -sf /tmp/circle-generated-current/circle_schema_generated.h \
/tmp/circle-include-current/mio/circle/schema_generated.h
ln -sf /tmp/circle-generated-current/circle_schema_generated.h \
/tmp/circle-generated-current/circle/schema_generated.h
clang++ -std=c++17 -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer \
-I/tmp/flatbuffers-23.5.26/include \
-I/tmp/circle-include-current \
-Iresearch/triage/audits/circle-2026-06-26/ONE/compiler/mio-circle/include \
-Iresearch/triage/audits/circle-2026-06-26/ONE/compiler/circledump/include \
-Iresearch/triage/audits/circle-2026-06-26/ONE/compiler/circledump/src \
research/triage/audits/circle-2026-06-26/poc/circledump_direct_driver.cpp \
research/triage/audits/circle-2026-06-26/ONE/compiler/circledump/src/Dump.cpp \
research/triage/audits/circle-2026-06-26/ONE/compiler/circledump/src/MetadataPrinter.cpp \
research/triage/audits/circle-2026-06-26/ONE/compiler/circledump/src/OpPrinter.cpp \
research/triage/audits/circle-2026-06-26/ONE/compiler/mio-circle/src/Reader.cpp \
research/triage/audits/circle-2026-06-26/ONE/compiler/mio-circle/src/Helper.cpp \
/tmp/flatbuffers-23.5.26-build/libflatbuffers.a \
-o /tmp/circledump_direct_driver_current
ASAN_OPTIONS=abort_on_error=0:symbolize=1 \
/tmp/circledump_direct_driver_current \
research/triage/audits/circle-2026-06-26/poc/external_offset_oob.circle
Observed:
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 1
circledump::dump_buffer(...) Dump.cpp:48
circledump::dump_model(...) Dump.cpp:404
operator<<(...) Dump.cpp:479
circledump_direct_driver.cpp:41
0 bytes after 232-byte region
Scanner Results
mfv-scan completed successfully:
tools/model-format-workbench/mfv-scan \
research/triage/audits/circle-2026-06-26/poc/external_offset_oob.circle \
--out /tmp/mfv-scan-circle-external-oob \
--timeout 180
Relevant results:
- ModelAudit: no security issues detected.
- ModelScan: no issues; scanned zero model files because Circle is unsupported.
- PickleScan: not pickle; no dangerous globals.
- Magika/file: generic unknown/data detection.
This is useful report framing: generic model scanners miss the malformed Circle external-buffer span, while the format-aware reader accepts the file and returns an unsafe pointer/size pair.
Duplicate Sweep
Local:
- No prior local Circle submission found in
research/triage. - Existing local offset/size work is OpenVINO/GGUF/other formats, not Circle.
GitHub:
gh search issues '"external buffer" "offset" "circle"' --repo Samsung/ONE --limit 20: no results.gh search issues '"buffer_info" "offset"' --repo Samsung/ONE --limit 20: no results.gh search issues '"mio_circle" "buffer_info"' --repo Samsung/ONE --limit 20: no results.gh search issues '"Circle" "heap-buffer-overflow"' --repo Samsung/ONE --limit 20: no results.
Web:
- Searches for exact
mio_circle::Reader/buffer_info/Circle external buffer offset sizedid not surface a matching public report. - Search noise included unrelated
pybind11 buffer_infoand Samsung non-ONE vulnerabilities.
Duplicate risk: low for exact bug class in Circle external buffers.
Next Steps
- Search ONE runtime paths for production consumers of external-buffer
offset/size, especially tensor constant loaders. - If only developer tooling is affected, submit carefully as malformed model file causing heap OOB read in shipped Circle inspection tooling.
- If a runtime loader consumes the same unchecked span, upgrade the report impact.