Skip to content

fix(ext/ffi): retain backing store references in nonblocking calls#32775

Merged
bartlomieju merged 2 commits intomainfrom
fix/ffi-nonblocking-backing-store
Mar 16, 2026
Merged

fix(ext/ffi): retain backing store references in nonblocking calls#32775
bartlomieju merged 2 commits intomainfrom
fix/ffi-nonblocking-backing-store

Conversation

@bartlomieju
Copy link
Copy Markdown
Member

Nonblocking FFI calls extract raw pointers from ArrayBuffer backing stores and send them to a background thread via spawn_blocking, but without retaining a reference to the backing store. If V8's garbage collector runs before the background thread completes, the backing store can be freed, leaving the native code with a dangling pointer.

Fix by collecting SharedRef references alongside the raw pointers for buffer, struct, and out_buffer arguments in nonblocking calls, and moving them into the spawn_blocking closure so they are kept alive for the duration of the native call.

Nonblocking FFI calls extract raw pointers from ArrayBuffer backing
stores and send them to a background thread via spawn_blocking, but
without retaining a reference to the backing store. If V8's garbage
collector runs before the background thread completes, the backing
store can be freed, leaving the native code with a dangling pointer.

Fix by collecting SharedRef<BackingStore> references alongside the raw
pointers for buffer, struct, and out_buffer arguments in nonblocking
calls, and moving them into the spawn_blocking closure so they are kept
alive for the duration of the native call.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@kajukitli kajukitli left a comment

Choose a reason for hiding this comment

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

lgtm — solid fix for the UAF in nonblocking FFI

the BackingStoreHolder pattern is clean: grab SharedRef<BackingStore> before extracting raw pointers, move holder into the spawn_blocking closure, explicit drop() after the call to make intent clear

test coverage is good: fills buffer with known pattern, forces GC while native sleeps, validates checksum on return

Copy link
Copy Markdown
Member

@littledivy littledivy left a comment

Choose a reason for hiding this comment

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

lgtm

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bartlomieju bartlomieju enabled auto-merge (squash) March 16, 2026 18:09
@bartlomieju bartlomieju merged commit 764ce2f into main Mar 16, 2026
112 checks passed
@bartlomieju bartlomieju deleted the fix/ffi-nonblocking-backing-store branch March 16, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants