From fabca3dee9396a26f0db028f03fba5f37af589e1 Mon Sep 17 00:00:00 2001 From: "Steven Zimmerman, CPA" <15812269+EffortlessSteven@users.noreply.github.com> Date: Wed, 29 Jul 2026 19:31:24 -0400 Subject: [PATCH] test(ffi): remove the toBuffer no-finalizer workaround The FFI runner's `primitives` test passed `getNoopDeallocatorCallback()` to `toBuffer`/`toArrayBuffer` so it would not hit the no-finalizer path, which adopted the caller's pointer as owned and freed it on GC. That path is fixed, so the workaround only hides the coverage: drop the callback and let the compiled fixture exercise the real default, wrapping static native storage, dropping the Buffer, forcing GC, then reading the pointer again. `getNoopDeallocatorCallback` has no other users, so remove it from the symbol descriptor, the destructuring, and the fixture. The real deallocator-counter helpers stay. Without the toBuffer fix this is red: the fixture segfaults the test runner (`panic(main thread): Segmentation fault`), which is what oven-sh/bun#35405 reports and why `run ffi > primitives` flaked on Windows. --- test/js/bun/ffi/ffi-test.c | 4 ---- test/js/bun/ffi/ffi.test.js | 12 ++++-------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/test/js/bun/ffi/ffi-test.c b/test/js/bun/ffi/ffi-test.c index 18f9d88a51ee..ae7ba120bb8d 100644 --- a/test/js/bun/ffi/ffi-test.c +++ b/test/js/bun/ffi/ffi-test.c @@ -118,14 +118,10 @@ uint32_t add_uint32_t(uint32_t a, uint32_t b) { return a + b; } uint64_t add_uint64_t(uint64_t a, uint64_t b) { return a + b; } FFI_EXPORT void *ptr_should_point_to_42_as_int32_t(); -FFI_EXPORT void *getNoopDeallocatorCallback(); static int32_t ffi_static_42 = 42; void *ptr_should_point_to_42_as_int32_t() { return &ffi_static_42; } -static void noop_deallocator(void *ptr, void *ctx) { (void)ptr; (void)ctx; } -void *getNoopDeallocatorCallback() { return &noop_deallocator; } - static uint8_t buffer_with_deallocator[128]; static int deallocatorCalled; FFI_EXPORT void deallocator(void *ptr, void *userData) { deallocatorCalled++; } diff --git a/test/js/bun/ffi/ffi.test.js b/test/js/bun/ffi/ffi.test.js index df08a74ed9dd..90c4ba3a8680 100644 --- a/test/js/bun/ffi/ffi.test.js +++ b/test/js/bun/ffi/ffi.test.js @@ -325,10 +325,6 @@ function getTypes(fast) { returns: "ptr", args: [], }, - getNoopDeallocatorCallback: { - returns: "ptr", - args: [], - }, getDeallocatorBuffer: { returns: "ptr", args: [], @@ -382,7 +378,6 @@ function ffiRunner(fast) { is_null, does_pointer_equal_42_as_int32_t, ptr_should_point_to_42_as_int32_t, - getNoopDeallocatorCallback, cb_identity_true, cb_identity_false, cb_identity_42_char, @@ -493,11 +488,12 @@ function ffiRunner(fast) { expect(cptr != 0).toBe(true); expect(typeof cptr === "number").toBe(true); expect(does_pointer_equal_42_as_int32_t(cptr)).toBe(true); - const noopDeallocator = getNoopDeallocatorCallback(); { - const buffer = toBuffer(cptr, 0, 4, noopDeallocator); + // No finalizer: both views borrow `cptr` (static storage in the fixture), + // so the GC below must not free it. See oven-sh/bun#35405. + const buffer = toBuffer(cptr, 0, 4); expect(buffer.readInt32(0)).toBe(42); - expect(new DataView(toArrayBuffer(cptr, 0, 4, noopDeallocator), 0, 4).getInt32(0, true)).toBe(42); + expect(new DataView(toArrayBuffer(cptr, 0, 4), 0, 4).getInt32(0, true)).toBe(42); expect(ptr(buffer)).toBe(cptr); } Bun.gc(true);