From 5768e16bf110e65ea89ae54647bed42dbd14cadf Mon Sep 17 00:00:00 2001 From: "Kamat, Trivikram" <16024985+trivikr@users.noreply.github.com> Date: Fri, 14 Aug 2026 07:56:24 -0700 Subject: [PATCH] ffi: validate DynamicLibrary getter receivers Check the receivers of the path, symbols, and functions getters before unwrapping them. This prevents incompatible receivers from crashing the process and makes the getters throw ERR_INVALID_THIS instead. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol --- src/node_ffi.cc | 22 ++++++++++++++++++++++ test/ffi/test-ffi-dynamic-library.js | 19 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/node_ffi.cc b/src/node_ffi.cc index 42c62c829168..8e00a75c02f0 100644 --- a/src/node_ffi.cc +++ b/src/node_ffi.cc @@ -751,7 +751,15 @@ void DynamicLibrary::InvokeCallback(ffi_cif* cif, } void DynamicLibrary::GetPath(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + if (!GetConstructorTemplate(env)->HasInstance(args.This())) { + THROW_ERR_INVALID_THIS(env, + "Value of \"this\" must be of type DynamicLibrary"); + return; + } + DynamicLibrary* lib = Unwrap(args.This()); + CHECK_NOT_NULL(lib); Local path; if (!ToV8Value(lib->env()->context(), lib->path_, args.GetIsolate()) @@ -806,9 +814,16 @@ void DynamicLibrary::GetFunction(const FunctionCallbackInfo& args) { void DynamicLibrary::GetFunctions(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); + if (!GetConstructorTemplate(env)->HasInstance(args.This())) { + THROW_ERR_INVALID_THIS(env, + "Value of \"this\" must be of type DynamicLibrary"); + return; + } + Isolate* isolate = env->isolate(); Local context = env->context(); DynamicLibrary* lib = Unwrap(args.This()); + CHECK_NOT_NULL(lib); if (lib->is_closed()) { THROW_ERR_FFI_LIBRARY_CLOSED(env); @@ -955,9 +970,16 @@ void DynamicLibrary::GetSymbol(const FunctionCallbackInfo& args) { void DynamicLibrary::GetSymbols(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); + if (!GetConstructorTemplate(env)->HasInstance(args.This())) { + THROW_ERR_INVALID_THIS(env, + "Value of \"this\" must be of type DynamicLibrary"); + return; + } + Isolate* isolate = env->isolate(); Local context = env->context(); DynamicLibrary* lib = Unwrap(args.This()); + CHECK_NOT_NULL(lib); if (lib->is_closed()) { THROW_ERR_FFI_LIBRARY_CLOSED(env); diff --git a/test/ffi/test-ffi-dynamic-library.js b/test/ffi/test-ffi-dynamic-library.js index 82400335a12f..b91dcb3eacc4 100644 --- a/test/ffi/test-ffi-dynamic-library.js +++ b/test/ffi/test-ffi-dynamic-library.js @@ -103,6 +103,25 @@ test('DynamicLibrary exposes functions and symbols', () => { } }); +test('DynamicLibrary getters reject incompatible receivers', () => { + const lib = new ffi.DynamicLibrary(libraryPath); + + try { + const getters = [ + Object.getOwnPropertyDescriptor(lib, 'path').get, + Object.getOwnPropertyDescriptor(lib, 'symbols').get, + Object.getOwnPropertyDescriptor( + ffi.DynamicLibrary.prototype, 'functions').get, + ]; + + for (const getter of getters) { + assert.throws(() => getter.call({}), { code: 'ERR_INVALID_THIS' }); + } + } finally { + lib.close(); + } +}); + test('DynamicLibrary evaluates function signatures once', () => { function makeChangingSignature() { const reads = { arguments: 0, return: 0 };