Skip to content

ffi: Fast API calls silently truncate out-of-range integer arguments #64613

Description

@trivikr

Version

main

Platform

macOS 26.5.2

Subsystem

ffi

What steps will reproduce the bug?

repro.c

#include <stdint.h>

int8_t i8(int8_t x) {
  return x;
}

uint8_t u8(uint8_t x) {
  return x;
}

int16_t i16(int16_t x) {
  return x;
}

uint16_t u16(uint16_t x) {
  return x;
}

int64_t i64(int64_t x) {
  return x;
}

Compile it by running

$ clang -dynamiclib repro.c -o librepro.dylib

repro.js

import { dlopen } from 'node:ffi';

const { functions } = dlopen(`./librepro.dylib`, {
  i8: { arguments: ['i8'], return: 'i8' },
  u8: { arguments: ['u8'], return: 'u8' },
  i16: { arguments: ['i16'], return: 'i16' },
  u16: { arguments: ['u16'], return: 'u16' },
  i64: { arguments: ['i64'], return: 'i64' },
});

function callI8(x) { return functions.i8(x); }
function callU8(x) { return functions.u8(x); }
function callI16(x) { return functions.i16(x); }
function callU16(x) { return functions.u16(x); }
function callI64(x) { return functions.i64(x); }

function optimize(fn, value) {
  eval('%PrepareFunctionForOptimization(fn)');
  fn(value);
  fn(value);
  eval('%OptimizeFunctionOnNextCall(fn)');
  fn(value);
}

for (const [fn, value] of [
  [callI8, 0],
  [callU8, 0],
  [callI16, 0],
  [callU16, 0],
  [callI64, 0n],
]) {
  optimize(fn, value);
}

console.log('i8:', callI8(128));
console.log('u8:', callU8(256));
console.log('i16:', callI16(32768));
console.log('u16:', callU16(65536));
console.log('i64:', callI64(2n ** 63n));

Run it

$ node --no-warnings --experimental-ffi --allow-natives-syntax repro.js

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior? Why is that the expected behavior?

Each call should throw ERR_INVALID_ARG_VALUE, as the generic FFI path does.

What do you see instead?

i8: -128
u8: 0
i16: -32768
u16: 0
i64: -9223372036854775808n

optimized FFI calls silently truncate or wrap every out-of-range argument

Additional information

No response

Metadata

Metadata

Assignees

Labels

ffiIssues and PRs related to experimental Foreign Function Interface support.

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions