wasm 記憶體越界讀寫測試#
手工編寫一個 wasm 模組,wat 代碼如下:
- 聲明需要一段記憶體空間
- 暴露兩個函數,寫記憶體和讀記憶體,之後在 js 代碼中調用
(module
;;聲明需要提供記憶體
(import "env" "memory" (memory 1 2)) ;; 初始 1 頁,最大 2 頁
;; 寫入 i32 到記憶體[offset]
(func (export "writeToMemory") (param i32) (param i32)
(i32.store
(local.get 0)
(local.get 1)
)
)
;; 從記憶體[offset] 讀取 i32
(func (export "readFromMemory") (param i32) (result i32)
(i32.load
(local.get 0)
)
)
)
然後編譯為 wasm 模組
wat2wasm memory_test.wat -o memory_test.wasm
編寫 js 代碼
const fs = require('fs');
(async () => {
const memory = new WebAssembly.Memory({ initial: 1, maximum: 2 });
const importObject = {
env: {
memory: memory
}
};
// 讀取wasm,分配記憶體
const wasmBuffer = fs.readFileSync('./memory_test.wasm');
const wasmModule = await WebAssembly.instantiate(wasmBuffer, importObject);
const { writeToMemory, readFromMemory} = wasmModule.instance.exports;
const inBoundsOffset = 65532; // 正常偏移
const outOfBoundsOffset = 70000; // 越界偏移
// 測試正常寫入和讀取
writeToMemory(inBoundsOffset, 123456);
console.log("讀取數據:", readFromMemory(inBoundsOffset));
try {
// 👇 試圖越界寫入
console.log("嘗試越界寫數據");
writeToMemory(outOfBoundsOffset, 999);
} catch (err) {
console.error("越界寫錯誤:", err.message);
console.log(err);
}
try {
// 👇 試圖越界讀取
console.log("嘗試越界讀數據");
console.log(readFromMemory(outOfBoundsOffset));
} catch (err) {
console.error("越界讀錯誤:", err.message);
console.log(err);
}
})();
運行結果,可以發現此時是報錯的
❯ node main.js
讀取數據: 123456
嘗試越界寫數據
越界寫錯誤: memory access out of bounds
RuntimeError: memory access out of bounds
at wasm://wasm/488cc87e:wasm-function[0]:0x59
at /Users/rayepeng/Documents/code/wasm-memory-test/main.js:26:5
嘗試越界讀數據
越界讀錯誤: memory access out of bounds
RuntimeError: memory access out of bounds
at wasm://wasm/488cc87e:wasm-function[1]:0x61
at /Users/rayepeng/Documents/code/wasm-memory-test/main.js:35:17