Skip to content

[Swift] Verify size-prefixed roots from reader position - #9196

Merged
mustiikhalil merged 2 commits into
google:masterfrom
carrerasdarren-cell:security/swift-size-prefixed-verifier-root
Aug 11, 2026
Merged

[Swift] Verify size-prefixed roots from reader position#9196
mustiikhalil merged 2 commits into
google:masterfrom
carrerasdarren-cell:security/swift-size-prefixed-verifier-root

Conversation

@carrerasdarren-cell

Copy link
Copy Markdown
Contributor

Summary

  • verify Swift roots from the active ByteBuffer.reader position
  • verify optional file identifiers from that same position
  • add regression coverage for malformed decoy roots, truncated identifiers, and a valid prefixed identifier

Problem

Both size-prefixed checked-root APIs call skipPrefix() before delegating to getCheckedRoot. The returned table is constructed from the post-prefix reader position, but verification previously followed a root offset from byte zero and checked a file identifier at byte four.

A malformed size-prefixed buffer could therefore place a valid decoy root where the verifier looked while returning a different malformed table from the post-prefix root. The same malformed table is rejected when checked directly, but the prefixed wrappers accepted it. Generated accessors or mutators could then operate outside the buffer bounds despite the checked API succeeding.

Fix

Capture the active reader position once and use it consistently for file-identifier verification, root verification, and table construction. The file-identifier bounds check now accounts for that position without wrapping on short buffers.

Validation

  • added a Swift regression covering both size-prefixed checked-root APIs
  • added short file-identifier bounds coverage and a valid prefixed control
  • parsed all modified Swift source and test files with swiftc
  • compiled the production Swift sources with a deterministic harness; direct malformed verification rejected, both patched prefixed paths rejected, a truncated identifier rejected, and a valid prefixed identifier was accepted
  • git diff --check passes

@mustiikhalil

Copy link
Copy Markdown
Collaborator

@carrerasdarren-cell Thanks for opening the PR. I was looking at the cpp approach. And it would be better if the swift implementation also follows a similar convention. Where we only skip after we have verified the prefixed value too. It's fine if we duplicate the logic for the verification here getPrefixedSizeCheckedRoot.

bool VerifySizePrefixedBuffer(const char* const identifier) {

TEST_EQ(VerifySizePrefixedMonsterBuffer(verifier), true);

Validate the size prefix before advancing ByteBuffer.reader, then use the active reader position consistently for root, file identifier, and returned-object verification. Cover malformed decoy roots, oversized prefixes, short identifiers, and valid prefixed identifiers.
@carrerasdarren-cell
carrerasdarren-cell force-pushed the security/swift-size-prefixed-verifier-root branch from b4a79a7 to 83b8c03 Compare August 7, 2026 07:22
@carrerasdarren-cell

Copy link
Copy Markdown
Contributor Author

Thanks, updated in 83b8c03. Both checked size-prefixed entry points now read and validate the UOffset prefix before calling skipPrefix(). getPrefixedSizeCheckedRoot applies the C++-style prefix <= available bytes check, while getCheckedPrefixedSizeRoot preserves its exact-size requirement. I also added an oversized-prefix regression that verifies rejection occurs without advancing ByteBuffer.reader. The production Swift modules compile with Swift 6.3.3, the modified sources/tests parse, git diff --check passes, and the deterministic malformed/valid harness still passes.

mustiikhalil
mustiikhalil previously approved these changes Aug 7, 2026

@mustiikhalil mustiikhalil left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! amazing work! one of the comments can be disregarded if not needed

Comment thread swift/Sources/FlatBuffers/Verifier.swift Outdated
Comment thread swift/Sources/FlatBuffers/Verifier.swift Outdated
Comment thread swift/Sources/FlatBuffers/Root.swift
@mustiikhalil

Copy link
Copy Markdown
Collaborator

@carrerasdarren-cell just pinging you so we can get this PR to the finish line

@carrerasdarren-cell

Copy link
Copy Markdown
Contributor Author

Thanks for the ping. I addressed the remaining wrapping-arithmetic nits in b76d5d5, replied to the optional placement suggestion, and resolved all three review threads. The production Swift module compiles cleanly locally with Swift 6.3.3; the refreshed CI run is now starting.

@mustiikhalil
mustiikhalil merged commit 5761d6e into google:master Aug 11, 2026
55 checks passed
@mustiikhalil

Copy link
Copy Markdown
Collaborator

@carrerasdarren-cell thanks for your contribution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants