Skip to content

Commit cf20171

Browse files
committed
ffi: validate DynamicLibrary getter receivers
Bind the path, symbols, and functions getter templates to the DynamicLibrary constructor signature. This causes V8 to reject incompatible receivers before invoking the native callbacks, preventing them from crashing the process. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol
1 parent 2899539 commit cf20171

2 files changed

Lines changed: 32 additions & 3 deletions

File tree

src/node_ffi.cc

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ using v8::MaybeLocal;
3535
using v8::Object;
3636
using v8::PropertyAttribute;
3737
using v8::ReadOnly;
38+
using v8::Signature;
3839
using v8::String;
3940
using v8::TryCatch;
4041
using v8::Value;
@@ -1238,16 +1239,23 @@ Local<FunctionTemplate> DynamicLibrary::GetConstructorTemplate(
12381239
tmpl = NewFunctionTemplate(isolate, DynamicLibrary::New);
12391240
tmpl->InstanceTemplate()->SetInternalFieldCount(
12401241
DynamicLibrary::kInternalFieldCount);
1242+
Local<Signature> signature = Signature::New(isolate, tmpl);
12411243

12421244
tmpl->InstanceTemplate()->SetAccessorProperty(
12431245
env->path_string(),
1244-
FunctionTemplate::New(env->isolate(), DynamicLibrary::GetPath),
1246+
FunctionTemplate::New(isolate,
1247+
DynamicLibrary::GetPath,
1248+
Local<Value>(),
1249+
signature),
12451250
Local<FunctionTemplate>(),
12461251
attributes);
12471252

12481253
tmpl->InstanceTemplate()->SetAccessorProperty(
12491254
FIXED_ONE_BYTE_STRING(isolate, "symbols"),
1250-
FunctionTemplate::New(env->isolate(), DynamicLibrary::GetSymbols),
1255+
FunctionTemplate::New(isolate,
1256+
DynamicLibrary::GetSymbols,
1257+
Local<Value>(),
1258+
signature),
12511259
Local<FunctionTemplate>(),
12521260
attributes);
12531261

@@ -1257,7 +1265,10 @@ Local<FunctionTemplate> DynamicLibrary::GetConstructorTemplate(
12571265
// reason.
12581266
tmpl->PrototypeTemplate()->SetAccessorProperty(
12591267
FIXED_ONE_BYTE_STRING(isolate, "functions"),
1260-
FunctionTemplate::New(env->isolate(), DynamicLibrary::GetFunctions),
1268+
FunctionTemplate::New(isolate,
1269+
DynamicLibrary::GetFunctions,
1270+
Local<Value>(),
1271+
signature),
12611272
Local<FunctionTemplate>(),
12621273
static_cast<PropertyAttribute>(ReadOnly));
12631274

test/ffi/test-ffi-dynamic-library.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,24 @@ test('DynamicLibrary exposes functions and symbols', () => {
124124
}
125125
});
126126

127+
test('DynamicLibrary getters reject incompatible receivers', () => {
128+
const lib = new ffi.DynamicLibrary(libraryPath);
129+
130+
try {
131+
const invalidGets = [
132+
() => Reflect.get(lib, 'path', {}),
133+
() => Reflect.get(lib, 'symbols', {}),
134+
() => Reflect.get(ffi.DynamicLibrary.prototype, 'functions', {}),
135+
];
136+
137+
for (const invalidGet of invalidGets) {
138+
assert.throws(invalidGet, TypeError);
139+
}
140+
} finally {
141+
lib.close();
142+
}
143+
});
144+
127145
test('DynamicLibrary evaluates function signatures once', () => {
128146
function makeChangingSignature() {
129147
const reads = { arguments: 0, return: 0 };

0 commit comments

Comments
 (0)