Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/node_ffi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,13 @@ MaybeLocal<Function> DynamicLibrary::CreateFunction(
bool has_ptr_args = use_sb && SignatureHasPointerArgs(*fn);
// Signatures that need JS-side conversion or validation use a wrapper, as
// do all fast signatures on platforms without a native library guard.
// Pointer arguments need the wrapper's range check because V8 truncates
// BigInts passed to Fast API uint64 parameters.
bool needs_fast_argument_wrapper =
use_fast_api && (SignatureNeedsRawPointerConversions(*fn) ||
SignatureNeedsFastIntegerValidation(*fn) ||
!info->fast_metadata->guards_library);
use_fast_api &&
(SignatureNeedsRawPointerConversions(*fn) ||
SignatureNeedsFastIntegerValidation(*fn) ||
SignatureHasPointerArgs(*fn) || !info->fast_metadata->guards_library);
// A single pointer-like parameter can get a separate Buffer-aware Fast API
// entrypoint so Buffer calls avoid JS pointer extraction.
bool needs_fast_buffer_invoke =
Expand Down
10 changes: 9 additions & 1 deletion test/ffi/test-ffi-fast-integer-validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,23 @@ test('fast FFI validates pointer BigInt ranges', () => {
arguments: [type, 'u64'],
return: 'u64',
});
// Only pointer-like arguments, so no integer type forces the wrapper.
const stringConcat = lib.getFunction('string_concat', {
arguments: [type, type],
return: 'pointer',
});
function callSingle(value) { return identityPointer(value); }

function callMultiple(value) { return sumBuffer(value, 0n); }

function callPointers(value) { return stringConcat(value, 0n); }

optimize(callSingle, 0n);
optimize(callMultiple, 0n);
optimize(callPointers, 0n);

const expect = { code: 'ERR_INVALID_ARG_VALUE' };
for (const call of [callSingle, callMultiple]) {
for (const call of [callSingle, callMultiple, callPointers]) {
assert.throws(() => call(-1n), expect);
assert.throws(() => call((2n ** 64n) + 5n), expect);
}
Expand Down
Loading