From 5849f885553c6ee1285bcd5c7736cec42ff9afd1 Mon Sep 17 00:00:00 2001 From: felipegenef Date: Sun, 17 May 2026 21:55:44 -0300 Subject: [PATCH 1/2] fix: coerce memory offsets to unsigned before typed array and DataView access --- targets/wasm_exec.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/targets/wasm_exec.js b/targets/wasm_exec.js index 15989b5b97..76876bd4e9 100644 --- a/targets/wasm_exec.js +++ b/targets/wasm_exec.js @@ -221,6 +221,8 @@ } const loadSlice = (array, len, cap) => { + array >>>= 0; + len >>>= 0; return new Uint8Array(this._inst.exports.memory.buffer, array, len); } @@ -233,6 +235,8 @@ } const loadString = (ptr, len) => { + ptr >>>= 0; + len >>>= 0; return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len)); } @@ -243,6 +247,9 @@ wasi_snapshot_preview1: { // https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) { + iovs_ptr >>>= 0; + iovs_len >>>= 0; + nwritten_ptr >>>= 0; let nwritten = 0; if (fd == 1) { for (let iovs_i=0; iovs_i { + bufPtr >>>= 0; + bufLen >>>= 0; crypto.getRandomValues(loadSlice(bufPtr, bufLen)); return 0; }, @@ -426,6 +435,8 @@ // valueLoadString(v ref, b []byte) "syscall/js.valueLoadString": (v_ref, slice_ptr, slice_len, slice_cap) => { + slice_ptr >>>= 0; + slice_len >>>= 0; const str = unboxValue(v_ref); loadSlice(slice_ptr, slice_len, slice_cap).set(str); }, @@ -437,6 +448,9 @@ // func copyBytesToGo(dst []byte, src ref) (int, bool) "syscall/js.copyBytesToGo": (ret_addr, dest_addr, dest_len, dest_cap, src_ref) => { + ret_addr >>>= 0; + dest_addr >>>= 0; + dest_len >>>= 0; let num_bytes_copied_addr = ret_addr; let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable @@ -456,6 +470,9 @@ // Originally copied from upstream Go project, then modified: // https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416 "syscall/js.copyBytesToJS": (ret_addr, dst_ref, src_addr, src_len, src_cap) => { + ret_addr >>>= 0; + src_addr >>>= 0; + src_len >>>= 0; let num_bytes_copied_addr = ret_addr; let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable From 1e5072f0bdedf03cac26ddfd62eb5efc5a347ac6 Mon Sep 17 00:00:00 2001 From: felipegenef Date: Mon, 18 May 2026 15:14:06 -0300 Subject: [PATCH 2/2] fix targets/wasm_exec.js: move unsigned coercions from helpers to top-level import functions --- targets/wasm_exec.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/targets/wasm_exec.js b/targets/wasm_exec.js index 76876bd4e9..2045a05de5 100644 --- a/targets/wasm_exec.js +++ b/targets/wasm_exec.js @@ -221,8 +221,6 @@ } const loadSlice = (array, len, cap) => { - array >>>= 0; - len >>>= 0; return new Uint8Array(this._inst.exports.memory.buffer, array, len); } @@ -235,8 +233,6 @@ } const loadString = (ptr, len) => { - ptr >>>= 0; - len >>>= 0; return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len)); } @@ -305,6 +301,8 @@ // func getRandomData(r []byte) "runtime.getRandomData": (slice_ptr, slice_len, slice_cap) => { + slice_ptr >>>= 0; + slice_len >>>= 0; crypto.getRandomValues(loadSlice(slice_ptr, slice_len, slice_cap)); }, @@ -342,12 +340,15 @@ // func stringVal(value string) ref "syscall/js.stringVal": (value_ptr, value_len) => { value_ptr >>>= 0; + value_len >>>= 0; const s = loadString(value_ptr, value_len); return boxValue(s); }, // func valueGet(v ref, p string) ref "syscall/js.valueGet": (v_ref, p_ptr, p_len) => { + p_ptr >>>= 0; + p_len >>>= 0; let prop = loadString(p_ptr, p_len); let v = unboxValue(v_ref); let result = Reflect.get(v, prop); @@ -356,6 +357,8 @@ // func valueSet(v ref, p string, x ref) "syscall/js.valueSet": (v_ref, p_ptr, p_len, x_ref) => { + p_ptr >>>= 0; + p_len >>>= 0; const v = unboxValue(v_ref); const p = loadString(p_ptr, p_len); const x = unboxValue(x_ref); @@ -364,6 +367,8 @@ // func valueDelete(v ref, p string) "syscall/js.valueDelete": (v_ref, p_ptr, p_len) => { + p_ptr >>>= 0; + p_len >>>= 0; const v = unboxValue(v_ref); const p = loadString(p_ptr, p_len); Reflect.deleteProperty(v, p); @@ -381,6 +386,11 @@ // func valueCall(v ref, m string, args []ref) (ref, bool) "syscall/js.valueCall": (ret_addr, v_ref, m_ptr, m_len, args_ptr, args_len, args_cap) => { + ret_addr >>>= 0; + m_ptr >>>= 0; + m_len >>>= 0; + args_ptr >>>= 0; + args_len >>>= 0; const v = unboxValue(v_ref); const name = loadString(m_ptr, m_len); const args = loadSliceOfValues(args_ptr, args_len, args_cap); @@ -396,6 +406,9 @@ // func valueInvoke(v ref, args []ref) (ref, bool) "syscall/js.valueInvoke": (ret_addr, v_ref, args_ptr, args_len, args_cap) => { + ret_addr >>>= 0; + args_ptr >>>= 0; + args_len >>>= 0; try { const v = unboxValue(v_ref); const args = loadSliceOfValues(args_ptr, args_len, args_cap); @@ -409,6 +422,9 @@ // func valueNew(v ref, args []ref) (ref, bool) "syscall/js.valueNew": (ret_addr, v_ref, args_ptr, args_len, args_cap) => { + ret_addr >>>= 0; + args_ptr >>>= 0; + args_len >>>= 0; const v = unboxValue(v_ref); const args = loadSliceOfValues(args_ptr, args_len, args_cap); try { @@ -427,6 +443,7 @@ // valuePrepareString(v ref) (ref, int) "syscall/js.valuePrepareString": (ret_addr, v_ref) => { + ret_addr >>>= 0; const s = String(unboxValue(v_ref)); const str = encoder.encode(s); storeValue(ret_addr, str);