Commit 75d55af1443 for nodejs

commit 75d55af14433072b12425b8fb4e7d56f1cfc8cba
Author: Trivikram Kamat <trivikr.dev@gmail.com>
Date:   Mon Nov 9 09:16:33 2026 -0800

    ffi: reject multi-argument buffer 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 other shapes 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
    PR-URL: https://github.com/nodejs/node/pull/67046
    Reviewed-By: Paolo Insogna <paolo@cowtech.it>

diff --git a/src/ffi/platforms/arm64.cc b/src/ffi/platforms/arm64.cc
index df215ecafed..25221958933 100644
--- a/src/ffi/platforms/arm64.cc
+++ b/src/ffi/platforms/arm64.cc
@@ -257,6 +257,11 @@ extern "C" bool node_ffi_create_fast_trampoline(
   if (has_buffer_args && fp_count != 0) {
     return false;
   }
+  // The buffer helper call clobbers target registers already loaded for
+  // earlier arguments, so buffer trampolines support a single argument only.
+  if (has_buffer_args && argc > 1) {
+    return false;
+  }

   const size_t incoming_gp_count = gp_count + (has_buffer_args ? 1 : 0);
   // When V8 passes FastApiCallbackOptions, it consumes one additional GP
diff --git a/src/ffi/platforms/x64.cc b/src/ffi/platforms/x64.cc
index d5c15c38157..f9700ac0211 100644
--- a/src/ffi/platforms/x64.cc
+++ b/src/ffi/platforms/x64.cc
@@ -378,6 +378,11 @@ extern "C" bool node_ffi_create_fast_trampoline(
   if (has_buffer_args && fp_count != 0) {
     return false;
   }
+  // The buffer helper call clobbers target registers already loaded for
+  // earlier arguments, so buffer trampolines support a single argument only.
+  if (has_buffer_args && argc > 1) {
+    return false;
+  }

   const size_t incoming_gp_count = gp_count + (has_buffer_args ? 1 : 0);
   // rdi is occupied by the V8 receiver, leaving rsi, rdx, rcx, r8, and r9 for