From c5f66033db707dded6c429846b71ee468d1bb560 Mon Sep 17 00:00:00 2001 From: "Kamat, Trivikram" <16024985+trivikr@users.noreply.github.com> Date: Wed, 22 Jul 2026 23:30:33 -0700 Subject: [PATCH] ffi: validate fast 32-bit integer argument ranges Add i32, int32, u32, and uint32 to Fast API integer validation so optimized calls reject invalid values instead of allowing V8 to coerce or truncate them. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.6-sol --- lib/internal/ffi/fast-api.js | 4 ++++ src/ffi/fast.cc | 3 ++- test/ffi/test-ffi-fast-integer-validation.js | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/internal/ffi/fast-api.js b/lib/internal/ffi/fast-api.js index c897f1baf9e6..2097cac6f6c1 100644 --- a/lib/internal/ffi/fast-api.js +++ b/lib/internal/ffi/fast-api.js @@ -50,6 +50,10 @@ const fastIntegerTypeInfo = { int16: { kind: 'number', min: -32768, max: 32767, label: 'an int16' }, u16: { kind: 'number', min: 0, max: 65535, label: 'a uint16' }, uint16: { kind: 'number', min: 0, max: 65535, label: 'a uint16' }, + i32: { kind: 'number', min: -2147483648, max: 2147483647, label: 'an int32' }, + int32: { kind: 'number', min: -2147483648, max: 2147483647, label: 'an int32' }, + u32: { kind: 'number', min: 0, max: 4294967295, label: 'a uint32' }, + uint32: { kind: 'number', min: 0, max: 4294967295, label: 'a uint32' }, i64: { kind: 'bigint', min: I64_MIN, max: I64_MAX, label: 'an int64' }, int64: { kind: 'bigint', min: I64_MIN, max: I64_MAX, label: 'an int64' }, u64: { kind: 'bigint', min: 0n, max: U64_MAX, label: 'a uint64' }, diff --git a/src/ffi/fast.cc b/src/ffi/fast.cc index 8c4420761fec..df8c4e79cba0 100644 --- a/src/ffi/fast.cc +++ b/src/ffi/fast.cc @@ -164,7 +164,8 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) { for (const std::string& name : fn.arg_type_names) { if (name == "bool" || name == "char" || name == "i8" || name == "int8" || name == "u8" || name == "uint8" || name == "i16" || name == "int16" || - name == "u16" || name == "uint16" || name == "i64" || name == "int64" || + name == "u16" || name == "uint16" || name == "i32" || name == "int32" || + name == "u32" || name == "uint32" || name == "i64" || name == "int64" || name == "u64" || name == "uint64") { return true; } diff --git a/test/ffi/test-ffi-fast-integer-validation.js b/test/ffi/test-ffi-fast-integer-validation.js index 49fd1364948c..26d51ae4248f 100644 --- a/test/ffi/test-ffi-fast-integer-validation.js +++ b/test/ffi/test-ffi-fast-integer-validation.js @@ -28,6 +28,10 @@ test('fast FFI validates integer argument ranges', () => { function callU16(value) { return functions.add_u16(value, 0); } + function callI32(value) { return functions.add_i32(value, 0); } + + function callU32(value) { return functions.add_u32(value, 0); } + function callI64(value) { return functions.add_i64(value, 0n); } function callU64(value) { return functions.add_u64(value, 0n); } @@ -37,6 +41,8 @@ test('fast FFI validates integer argument ranges', () => { [callU8, 0], [callI16, 0], [callU16, 0], + [callI32, 0], + [callU32, 0], [callI64, 0n], [callU64, 0n], ]) { @@ -48,6 +54,14 @@ test('fast FFI validates integer argument ranges', () => { assert.throws(() => callU8(256), expect); assert.throws(() => callI16(32768), expect); assert.throws(() => callU16(65536), expect); + assert.throws(() => callI32(2147483648), expect); + assert.throws(() => callI32(-2147483649), expect); + assert.throws(() => callI32(1.5), expect); + assert.throws(() => callI32('1'), expect); + assert.throws(() => callU32(4294967296), expect); + assert.throws(() => callU32(-1), expect); + assert.throws(() => callU32(1.5), expect); + assert.throws(() => callU32('1'), expect); assert.throws(() => callI64(2n ** 63n), expect); assert.throws(() => callU64(2n ** 64n), expect); } finally {