fix(core): getRandomValues fills the caller's typed array on iOS - #11405
Merged
NathanWalker merged 1 commit intoSep 3, 2026
Merged
Conversation
NSMutableData never aliases bytes it is handed: with freeWhenDone:NO it copies them on creation, with freeWhenDone:YES it copies them and frees the original. Wrapping V8's backing store in one therefore filled a private copy and left the caller's array zeroed, or double-freed the allocation. Hand the typed array to SecRandomCopyBytes directly; the runtime resolves a view to its backing store at the view's byte offset, so the fill lands in the caller's own window with nothing in between.
|
View your CI Pipeline Execution ↗ for commit 00d0102
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗ ☁️ Nx Cloud last updated this comment at |
commit: |
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.
PR Checklist
What is the current behavior?
On iOS,
crypto.getRandomValues(typedArray)returns the array unchanged: every byte stays zero. Any key, token, IV or nonce minted through it on the main thread or in a worker is all zeros.The shim wraps V8's backing store in
NSMutableData.dataWithBytesNoCopy:length:freeWhenDone:and letsNSCCrypto.getRandomValues:fillmutableBytes.NSMutableDatadoes not adopt foreign bytes, regardless of the ownership flag (measured on macOS 15 and the iOS simulator; only the immutableNSDataadopts them):NSData dataWithBytesNoCopy:… freeWhenDone:NONSMutableData dataWithBytesNoCopy:… freeWhenDone:NONSMutableData dataWithBytesNoCopy:… freeWhenDone:YESSo
freeWhenDone:YES(the previous code) filled a private copy and freed V8's allocation, which is the double-free that was fixed by switching toNO, andNOfills the same private copy and leaves the caller's array untouched. NoNSData-based construction can make the native fill reach the typed array.What is the new behavior?
The iOS branch hands the typed array to
SecRandomCopyBytesdirectly and checks the status. The runtime already passes anArrayBufferViewas its backing store pointer plus the view's byte offset (tns::TryGetBufferFromArrayBuffer), so the bytes land in the caller's own window with no intermediate object: zero copies and nothing for Foundation to own or free. A wider element type is still reinterpreted as a byte view over the same window.packages/core/references.d.tsnow references the Security framework typings. The Android branch is unchanged: the runtime maps the view to a directByteBufferover the same window and the Java side fills it in place.Specs assert that the very view reaches
SecRandomCopyByteswith its byte length, that an offset view and a reinterpretedUint32Arrayare filled within their window only and the bytes are visible through the caller's array, that a failure status throws, and that neitherNSMutableDatanorNSCCryptois involved.NSCCrypto.getRandomValues:(NSMutableData *)in NSCWinterTC is left as is; it is no longer used by core and itsNSMutableDatacontract cannot alias caller memory, so it is a candidate for deprecation when the framework is next rebuilt.