diff --git a/src/node_wasi.cc b/src/node_wasi.cc index 6c2adc826571..844221b88983 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 v); template static VT ConvertType(Local V); +// Wasm i32 values with the high bit set arrive as negative Int32 numbers. template <> bool CheckType(Local value) { - return value->IsUint32(); + return value->IsUint32() || value->IsInt32(); } template <> uint32_t ConvertType(Local value) { + if (value->IsInt32()) { + return static_cast(value.As()->Value()); + } return value.As()->Value(); } diff --git a/test/fixtures/wasi-high-bit-ptr.wasm b/test/fixtures/wasi-high-bit-ptr.wasm new file mode 100644 index 000000000000..78f123ffbde2 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 000000000000..5336be289364 --- /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 000000000000..e2ea0bdbc6c9 --- /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());