Skip to content

ffi: GC of DynamicLibrary frees registered callbacks still held by native code #66841

Open

Description

@trivikr

Version

main

Platform

macOS

Subsystem

ffi

What steps will reproduce the bug?

import { DynamicLibrary } from 'node:ffi';
const libraryPath = "../node/test/ffi/fixture_library/build/Release/ffi_test_library.dylib";

// A separate handle provides the native function that invokes the callback.
const keeper = new DynamicLibrary(libraryPath);
const call_int_callback = keeper.getFunction('call_int_callback',
  { arguments: ['pointer', 'i32'], return: 'i32' });

let lib = new DynamicLibrary(libraryPath);
const cbPtr = lib.registerCallback(
  { arguments: ['i32'], return: 'i32' }, (x) => x * 2);

console.log(call_int_callback(cbPtr, 21)); // 42

lib = null;      // drop the handle without calling close()
globalThis.gc(); // ~DynamicLibrary -> Close() -> ffi_closure_free

console.log(call_int_callback(cbPtr, 21)); // segmentation fault

Run with

node --expose-gc repro.mjs

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior? Why is that the expected behavior?

A callback pointer from library.registerCallback() should stay valid until the user calls library.close() or library.unregisterCallback(pointer). The docs only call it undefined behavior to invoke callback pointers after one of those explicit calls. Here neither was called.

What do you see instead?

The process crashes with a segmentation fault. Native code jumps into a freed ffi_closure trampoline, which is a use-after-free.

Additional information

No response

Activity

  1. self-assigned this
    on Oct 19, 2026
  2. added
    ffiIssues and PRs related to experimental Foreign Function Interface support.
    on Oct 19, 2026
  3. saqibsafwan4-code commented on Oct 19, 2026

    @saqibsafwan4-code
  4. saqibsafwan4-code commented on Oct 19, 2026

    @saqibsafwan4-code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

ffiIssues and PRs related to experimental Foreign Function Interface support.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions