Commit 1d5f8e6cba0 for nodejs

commit 1d5f8e6cba0cd5a7f939165a0bd0ca6c09e13ad1
Author: Guy Bedford <guybedford@gmail.com>
Date:   Mon Oct 19 09:56:07 2026 -0700

    wasi: accept wasm i32 pointers with high bit set

    Wasm i32 arguments with the high bit set are passed to JS as negative
    Int32 numbers, so WASI functions taking uint32_t pointers rejected
    them with EINVAL. Accept Int32 in CheckType<uint32_t> and reinterpret
    as uint32_t on conversion, fixing all WASI functions at once.

    Fixes: https://github.com/nodejs/node/issues/62671
    Refs: https://github.com/nodejs/node/pull/62822
    Assisted-by: OpenCode
    Signed-off-by: Guy Bedford <guybedford@gmail.com>
    PR-URL: https://github.com/nodejs/node/pull/66636
    Reviewed-By: James M Snell <jasnell@gmail.com>

diff --git a/src/node_wasi.cc b/src/node_wasi.cc
index 6c2adc82657..844221b8898 100644
--- a/src/node_wasi.cc
+++ b/src/node_wasi.cc
@@ -36,6 +36,7 @@ using v8::FastApiCallbackOptions;
 using v8::FunctionCallbackInfo;
 using v8::FunctionTemplate;
 using v8::HandleScope;
+using v8::Int32;
 using v8::Integer;
 using v8::Isolate;
 using v8::Local;
@@ -296,13 +297,17 @@ static bool CheckType(Local<Value> v);
 template <typename VT>
 static VT ConvertType(Local<Value> V);

+// Wasm i32 values with the high bit set arrive as negative Int32 numbers.
 template <>
 bool CheckType<uint32_t>(Local<Value> value) {
-  return value->IsUint32();
+  return value->IsUint32() || value->IsInt32();
 }

 template <>
 uint32_t ConvertType(Local<Value> value) {
+  if (value->IsInt32()) {
+    return static_cast<uint32_t>(value.As<Int32>()->Value());
+  }
   return value.As<Uint32>()->Value();
 }

diff --git a/test/fixtures/wasi-high-bit-ptr.wasm b/test/fixtures/wasi-high-bit-ptr.wasm
new file mode 100644
index 00000000000..78f123ffbde
Binary files /dev/null and b/test/fixtures/wasi-high-bit-ptr.wasm differ
diff --git a/test/fixtures/wasi-high-bit-ptr.wat b/test/fixtures/wasi-high-bit-ptr.wat
new file mode 100644
index 00000000000..5336be28936
--- /dev/null
+++ b/test/fixtures/wasi-high-bit-ptr.wat
@@ -0,0 +1,22 @@
+;; Build: wasm-tools parse wasi-high-bit-ptr.wat -o wasi-high-bit-ptr.wasm
+(module
+  (import "wasi_snapshot_preview1" "clock_time_get"
+    (func $clock_time_get (param i32 i64 i32) (result i32)))
+  (import "wasi_snapshot_preview1" "args_sizes_get"
+    (func $args_sizes_get (param i32 i32) (result i32)))
+  (memory (export "memory") 1)
+  (func (export "_start"))
+  (func (export "clock_time_get_high_ptr") (result i32)
+    i32.const 0
+    i64.const 1
+    i32.const 0x80000000
+    call $clock_time_get)
+  (func (export "clock_time_get_low_ptr") (result i32)
+    i32.const 0
+    i64.const 1
+    i32.const 8
+    call $clock_time_get)
+  (func (export "args_sizes_get_high_ptr") (result i32)
+    i32.const 0x80000000
+    i32.const 0xfffffff0
+    call $args_sizes_get))
diff --git a/test/wasi/test-wasi-high-bit-ptr.js b/test/wasi/test-wasi-high-bit-ptr.js
new file mode 100644
index 00000000000..e2ea0bdbc6c
--- /dev/null
+++ b/test/wasi/test-wasi-high-bit-ptr.js
@@ -0,0 +1,24 @@
+'use strict';
+// Wasm i32 arguments with the high bit set arrive in JS as negative Int32
+// numbers. WASI functions must reinterpret them as uint32 pointers rather
+// than rejecting them with EINVAL.
+const common = require('../common');
+const assert = require('assert');
+const fixtures = require('../common/fixtures');
+const { WASI } = require('wasi');
+
+const UVWASI_EOVERFLOW = 61;
+
+(async () => {
+  const wasi = new WASI({ version: 'preview1', returnOnExit: true });
+  const importObject = { wasi_snapshot_preview1: wasi.wasiImport };
+  const { instance } = await WebAssembly.instantiate(
+    fixtures.readSync('wasi-high-bit-ptr.wasm'), importObject);
+  wasi.start(instance);
+
+  assert.strictEqual(instance.exports.clock_time_get_low_ptr(), 0);
+  assert.strictEqual(instance.exports.clock_time_get_high_ptr(),
+                     UVWASI_EOVERFLOW);
+  assert.strictEqual(instance.exports.args_sizes_get_high_ptr(),
+                     UVWASI_EOVERFLOW);
+})().then(common.mustCall());