Skip to content

Fix heap OOB read in reflection-based Verify() from unchecked Type.index() - #9198

Open
prasanna8585 wants to merge 1 commit into
google:masterfrom
prasanna8585:fix/reflection-verify-oob-index
Open

Fix heap OOB read in reflection-based Verify() from unchecked Type.index()#9198
prasanna8585 wants to merge 1 commit into
google:masterfrom
prasanna8585:fix/reflection-verify-oob-index

Conversation

@prasanna8585

Copy link
Copy Markdown

Summary

VerifyUnion, VerifyVector, and VerifyObject in reflection.cpp use field.type()->index() to index into schema.objects()/schema.enums() without validating the index is in range. Vector::Get()'s only bounds check is an assert that is compiled out in NDEBUG (release) builds, so a schema with an out-of-range Type.index() causes an out-of-bounds read when verified via the reflection API.

Who is affected

Applications that call flatbuffers::Verify(schema, root, buf, len) with a schema from an untrusted or externally supplied source (e.g. tools that load .bfbs schemas at runtime, per the documented reflection use case).

Fix

Adds a range check (0 <= index() < size()) at each of the three call sites in the verification path before calling Get(), returning false (verification failure) on an out-of-range index rather than reading out of bounds.

Testing

  • Added ReflectionInvalidObjectIndexTest to tests/reflection_test.cpp, which builds a schema with an empty objects vector and a field type.index() far out of range, and confirms Verify() now fails closed.
  • Confirmed via local build that this test aborts (hits the Vector::Get assert) against the unfixed source, and passes cleanly with the fix applied.
  • Full existing test suite (flattests) passes with no regressions.

Note for maintainers

CopyTable/CopyInline (roughly lines 680-757) have the same unchecked index() pattern, but they operate on data that callers are expected to have already run through Verify(). Left out of this fix to keep the change minimal and focused on the verification path itself; flagging here in case it's worth a follow-up.

…dex()

VerifyUnion, VerifyVector, and VerifyObject in reflection.cpp use
field.type()->index() to index into schema.objects()/schema.enums()
without validating the index is in range. Vector::Get()'s only bounds
check is an assert that is compiled out in NDEBUG (release) builds, so
a schema with an out-of-range Type.index() causes an out-of-bounds read
when verified via the reflection API. This affects callers using
flatbuffers::Verify() with a schema from an untrusted or externally
supplied source.

Adds bounds checks at all three affected call sites so verification
fails closed instead, plus a regression test that builds a schema with
an empty objects vector and an out-of-range field type.index(), and
confirms Verify() now returns false instead of reading out of bounds.

Note: CopyTable/CopyInline (~L680-757) have the same unchecked index()
pattern but operate on data expected to already be verified; leaving
those out of this fix to keep it minimal and reviewable, flagging for
a maintainer look separately.
@github-actions github-actions Bot added c++ codegen Involving generating code from schema labels Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ codegen Involving generating code from schema

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant