[Swift] Fix verifier accepting truncated scalar vectors (OOB read/write, RCE)#9081
Merged
mustiikhalil merged 1 commit intogoogle:masterfrom May 8, 2026
Merged
Conversation
Collaborator
|
@alimezar Thanks for your PR, I am wondering if you can wait on merging it until the following PR lands (should be today). 1- If the swift Testing changes land today, then you would need to convert the test case to use swift testing, and if possible add a link to the ticket similar to the example below:
|
Contributor
Author
|
Hi @mustiikhalil. The IssueTracker entry is private so I've opened a public issue Regarding the PR I dont mind waiting, once it lands I'll rebase and convert the regression test to Swift Testing. Thank you. |
Collaborator
|
@alimezar Swift testing PR is merged |
…te, RCE) getCheckedRoot accepted malformed FlatBuffers whose scalar vector element count did not match the available payload bytes. After verification succeeded, the generated accessors and mutators read and wrote past ByteBuffer.capacity, producing out-of-bounds memory disclosure, out-of-bounds memory corruption, and code execution when the corrupted adjacent control data was later invoked. Root cause: verifyRange passed the vector element count to rangeInBuffer as a byte count. For any scalar vector whose element size is greater than one byte (e.g. [long], [int], [double]), the declared length only had to be at most byteBuffer.capacity bytes beyond the vector header, instead of count * elementSize bytes, so a buffer declaring N elements but containing only N raw bytes was accepted. Fix: multiply the declared element count by MemoryLayout<T>.size with overflow detection and pass the resulting byte size to rangeInBuffer, so truncated scalar vectors are rejected before any unsafe generated access can occur. Adds a regression test that builds a Swift_Tests_Vectors-shaped buffer declaring a length-2 ulong vector backed by only 2 bytes of payload and asserts getCheckedRoot throws.
d36820c to
4cc88dc
Compare
Contributor
Author
|
Hi @mustiikhalil, Rebased onto master and converted the regression test to Swift Testing. |
mustiikhalil
approved these changes
May 8, 2026
Collaborator
mustiikhalil
left a comment
There was a problem hiding this comment.
LGTM!
@alimezar Thanks for opening a PR, and help improving the swift port 🎉
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
getCheckedRootaccepted malformed FlatBuffers whose scalar vector element count did not match the available payload bytes. After verification succeeded, the generated accessors and mutators read and wrote pastByteBuffer.capacity, producing out-of-bounds memory disclosure, out-of-bounds memory corruption, and code execution when corrupted adjacent control data was later invoked.Reported as Google IssueTracker issue 510740173.
Root cause
Verifiable.verifyRangepassed the vector element count directly torangeInBufferas a byte count. For any scalar vector whose element size is greater than one byte (e.g.[long],[int],[double]), the declared length only had to fitbyteBuffer.capacitybytes after the vector header instead ofcount * elementSizebytes, so a buffer declaring N elements but containing only N raw bytes was accepted.Fix
Multiply the declared element count by
MemoryLayout<T>.sizewith overflow detection and pass the resulting byte size torangeInBuffer, so truncated scalar vectors are rejected at verification time before any unsafe generated access can occur.