diff --git a/lib/internal/ffi/fast-api.js b/lib/internal/ffi/fast-api.js index a232caa1af24..f901fd6d80c8 100644 --- a/lib/internal/ffi/fast-api.js +++ b/lib/internal/ffi/fast-api.js @@ -15,7 +15,7 @@ const { } = require('buffer'); const { - isAnyArrayBuffer, + isArrayBuffer, isArrayBufferView, } = require('internal/util/types'); @@ -125,7 +125,7 @@ function hasStringPointerArg(type, value) { function hasPointerMemoryArg(type, value) { return (needsRawPointerConversion(type) || needsStringPointerConversion(type)) && - (isArrayBufferView(value) || isAnyArrayBuffer(value)); + (isArrayBufferView(value) || isArrayBuffer(value)); } function enterStringConversion(state) { @@ -283,7 +283,7 @@ function wrapWithRawPointerConversions(rawFn, argumentTypes, owner) { } finally { exitStringConversion(stringState); } - } else if (memory0 && (isArrayBufferView(arg) || isAnyArrayBuffer(arg))) { + } else if (memory0 && (isArrayBufferView(arg) || isArrayBuffer(arg))) { if (fastBufferInvoke !== undefined) { return fastBufferInvoke(arg); } diff --git a/src/ffi/fast.cc b/src/ffi/fast.cc index 80ee49e08b28..58d63dec7dde 100644 --- a/src/ffi/fast.cc +++ b/src/ffi/fast.cc @@ -247,13 +247,14 @@ extern "C" uintptr_t node_ffi_fast_buffer_data(v8::Local value, // invalid pointer value. constexpr uintptr_t kInvalidBuffer = std::numeric_limits::max(); - // Accept only memory-backed JS values in the native helper. Other pointer - // conversions, including strings, stay in the JS wrapper so their temporary - // lifetime is explicit. + // Accept only the memory-backed JS values supported by ToFFIArgument in the + // native helper. Other pointer conversions, including strings and direct + // SharedArrayBuffers, stay in the JS wrapper so validation and temporary + // lifetimes match the generic path. if (value->IsArrayBufferView()) { return PointerFromValue(value); } - if (value->IsArrayBuffer() || value->IsSharedArrayBuffer()) { + if (value->IsArrayBuffer()) { return PointerFromValue(value); } diff --git a/test/ffi/test-ffi-fast-buffer.js b/test/ffi/test-ffi-fast-buffer.js index e4399ee8ee47..822b26ee9a09 100644 --- a/test/ffi/test-ffi-fast-buffer.js +++ b/test/ffi/test-ffi-fast-buffer.js @@ -1,4 +1,4 @@ -// Flags: --experimental-ffi --expose-internals +// Flags: --experimental-ffi --expose-internals --allow-natives-syntax 'use strict'; const common = require('../common'); @@ -70,6 +70,31 @@ test('fast FFI buffer arguments reject invalid values', () => { } }); +test('optimized pointer arguments reject direct SharedArrayBuffers', () => { + const lib = new ffi.DynamicLibrary(libraryPath); + const firstByte = lib.getFunction('first_byte', { + arguments: ['pointer'], + return: 'u8', + }); + const regular = new ArrayBuffer(1); + const shared = new SharedArrayBuffer(1); + const expected = { code: 'ERR_INVALID_ARG_VALUE' }; + + try { + assert.throws(() => firstByte(shared), expected); + + eval('%PrepareFunctionForOptimization(firstByte)'); + firstByte(regular); + firstByte(regular); + eval('%OptimizeFunctionOnNextCall(firstByte)'); + firstByte(regular); + + assert.throws(() => firstByte(shared), expected); + } finally { + lib.close(); + } +}); + test('fast FFI string buffers survive reentrant callbacks', { // Bundled libffi callbacks crash on SmartOS. skip: common.isSunOS,