做者:Lin Clark
译者:xlaoyu
英文原文:WebAssembly table imports… what are they?web
转载请注明出处,保留原文连接以及做者信息数组
这是 WebAssembly 使用系列介绍的第二篇文章:安全
在第一篇文章中已经介绍过能够导入 WebAssembly 模块实例中四种不一样类型的值了:ide
前三种咱们都见过用过或者在以前的文章介绍了,可是对于最后一个可能你们都会疑惑:它究竟是什么和有什么做用?函数
在 JS 中,咱们都知道函数表达式能赋值给一个变量,换一种说法便是变量指向了函数。而后咱们可使用这个变量(函数表达式)作一些事情,好比将它传递给另一个函数做为回调函数:fetch
在 C 语言中这个变量被称为函数指针(function pointers)。函数保存在内存中,而这个变量(函数指针)仅仅保存的是指向该函数的内存地址(memory address)。ui
这个指针变量能根据咱们的须要在不一样时间指向不一样的函数(也就是不一样的内存地址),若是学过 C 或者 C++ 对这个概念应该不陌生。this
在网页中,咱们都知道全部函数实际也是一个 JavaScript 对象,而且因为这个特性,因此它们所使用的内存地址在 WebAssembly 的内存区域外。spa
若是咱们想在 WebAssembly 中拥有一个指向该函数的变量,那么咱们须要获取到该函数的地址而且放入 WebAssembly 内存中。prototype
可是保证网页安全的其中一点就是须要保持内存地址的不可见性,咱们不但愿页面中的代码可以查看而且修改那些内存地址。想象一下,若是页面中存在恶意代码而且能修改内存,那么它们将能够利用内存相关知识去制造漏斗。
举个🌰,它能够去把某个指向函数地址的变量改成指向另一个函数的地址(一个恶意函数),那么当用户尝试去调用该变量(函数)时,就触发了攻击者的指定的任何内容了。
恶意代码可能会以任何方式插入到页面中,也许就在某个字符串里。这时候咱们须要一种机制来实现安全的函数指针 -- table。
WebAssembly 的 table 类型能使咱们在避免遭受各类攻击的方式下使用函数指针特性。
table
是一个位于 WebAssembly 内存以外的数组,它的值就是对函数的引用。
在底层,引用就是内存地址。但因为它不在 WebAssembly 的内存中,所以 WebAssembly 没法看到这些地址,可是它能够访问到数组索引。
当 WebAssembly 模块想要去调用这些函数的时候,可使用数组索引经过所谓的 间接调用(call_indirect)
Table.prototype.get 去调用函数。
Ps:一下是译者引用 MDN 上的一段代码和注释
var tbl = new WebAssembly.Table({initial:2, element:"anyfunc"});
console.log(tbl.length); // "2"
console.log(tbl.get(0)); // "null"
console.log(tbl.get(1)); // "null"
var importObj = {
js: {
tbl:tbl
}
};
// 假设 table2.wasm 包含两个函数(一个返回42,另外一个返回43)而后把两个函数存储在 table 的 0 和 1 索引位置中
WebAssembly.instantiateStreaming(fetch('table2.wasm'), importObject)
.then(function(obj) {
console.log(tbl.length);
console.log(tbl.get(0)()); // 42
console.log(tbl.get(1)()); // 43
});
复制代码
element - A string representing the type of value to be stored in the table. At the moment this can only have a value of "anyfunc" (functions). initial - The initial number of elements of the WebAssembly Table.
如今,表格的用例很是有限。它们被添加到规范中以支持这些函数指针,由于 C 和 C++ 很是依赖这些函数指针。
正由于如此,目前咱们能够放入表中的惟一引用是对函数的引用。可是随着WebAssembly功能的扩展(例如,当添加对DOM的直接访问时),咱们能看到 table 上保存更多类型的引用以及执行除了间接引用外其余的操做。