mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
## Summary - **PROPERTY_NAME_FROM_UTF8 use-after-free:** The macro used `StringImpl::createWithoutCopying` for ASCII strings, which left dangling pointers in JSC's atom string table when the caller freed the input buffer (e.g. napi-rs `CString`). Fixed by using `Identifier::fromString` which copies only when inserting into the atom table, but never retains a reference to the caller's buffer. - **napi_create_external_buffer data lifetime:** `finalize_cb` was attached via `addFinalizer` (tied to GC of the `JSUint8Array` view) instead of the `ArrayBuffer` destructor. Extracting `.buffer` and letting the Buffer get GC'd would free the backing data while the `ArrayBuffer` still referenced it. Fixed by attaching the destructor to the `ArrayBuffer` via `createFromBytes`, using an armed `NapiExternalBufferDestructor` to safely handle the `JSUint8Array::create` error path. Closes #26446 Closes #26423 ## Test plan - [x] Added regression test `test_napi_get_named_property_copied_string` -- strdup/free cycles with GC to reproduce the atom table dangling pointer - [x] Added regression test `test_external_buffer_data_lifetime` -- extracts ArrayBuffer, drops Buffer, GCs, verifies data is intact - [x] Both tests pass with `bun bd test` and match Node.js output via `checkSameOutput` - [x] Verified `test_external_buffer_data_lifetime` fails without the fix (data corrupted) and passes on Node.js - [x] Verified impit reproducer from #26423 works correctly with the fix Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>