From 67e402863f4603187545347ae79e47fa10b62204 Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Mon, 26 Oct 2026 22:46:17 -0700 Subject: [PATCH] ffi: reject non-leading buffer args in fast trampolines The arm64 and x86_64 SysV emitters convert each buffer argument with a helper call after loading earlier arguments into their target registers. The call clobbers those registers, so the target would receive wrong values for every argument before the buffer. This is not reachable today: buffer-typed trampolines are generated only for single-argument signatures. Reject the unsupported shape in the emitters so a future caller falls back instead of miscompiling. Signed-off-by: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Assisted-by: claude:opus-5.5 --- src/ffi/platforms/arm64.cc | 5 +++++ src/ffi/platforms/x64.cc | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/ffi/platforms/arm64.cc b/src/ffi/platforms/arm64.cc index df215ecafed3..8ff0f1c959d1 100644 --- a/src/ffi/platforms/arm64.cc +++ b/src/ffi/platforms/arm64.cc @@ -243,6 +243,11 @@ extern "C" bool node_ffi_create_fast_trampoline( if (IsFloatType(args[i])) { fp_count++; } else { + // The buffer helper call clobbers target registers already loaded for + // earlier arguments, so only a leading buffer argument is supported. + if (IsPointerValueType(args[i]) && gp_count != 0) { + return false; + } gp_count++; has_buffer_args = has_buffer_args || IsPointerValueType(args[i]); } diff --git a/src/ffi/platforms/x64.cc b/src/ffi/platforms/x64.cc index d5c15c381574..0167bc7b5aac 100644 --- a/src/ffi/platforms/x64.cc +++ b/src/ffi/platforms/x64.cc @@ -367,6 +367,11 @@ extern "C" bool node_ffi_create_fast_trampoline( if (IsFloatType(args[i])) { fp_count++; } else { + // The buffer helper call clobbers target registers already loaded for + // earlier arguments, so only a leading buffer argument is supported. + if (IsPointerValueType(args[i]) && gp_count != 0) { + return false; + } gp_count++; has_buffer_args = has_buffer_args || IsPointerValueType(args[i]); }