[译] WebAssembly中的内存(为何它比你想象的更安全)


title: WebAssembly中的内存(为何它比你想象的更安全)javascript

date: 2018-3-22 23:58:00java

categories: 翻译web

tags: WebAssembly数组

source: 原文地址浏览器

auther: Lin Clark安全


WebAssembly中的内存(为何它比你想象的更安全)


这是此系列的第二篇文章:函数


WebAssembly中的内存与JavaScript中的内存稍有不一样。使用WebAssembly,您能够直接访问原始字节...而且会让一些人感到担心。但它实际上比你想象的更安全。工具

什么是memory对象?

当一个WebAssembly模块被实例化时,它须要一个内存对象。你能够建立一个新的WebAssembly.Memory对象并将该对象传入。若是不存在,则会建立一个内存对象并将其自动附加到该实例。编码

全部JS引擎在内部都会建立一个ArrayBuffer(我在另外一篇文章中解释过)。ArrayBuffer是一个对象,JS对其保持引用。JS为你分配内存。你告诉它须要多少内存,它会建立一个给定大小的ArrayBuffer。翻译

数组的索引能够看做是内存地址。若是须要更多的内存,你能够作一些叫作 growing(增加) 的事情来扩大数组。

将WebAssembly的内存做为JavaScript中的一个对象 - 做为ArrayBuffer处理 - 作到了两件事:

  1. 便于JS和WebAssembly之间的传值
  2. 使内存管理更加安全

在JS和WebAssembly之间传递值

由于这只是一个JavaScript对象,这意味着JavaScript也能够挖掘出这些内存中的字节。于此,WebAssembly和JavaScript能够经过共享内存并来回传递值。

他们不使用内存地址,而是使用数组索引来访问每一个box(内存单元)。

例如,WebAssembly能够在内存中放置一个字符串。它会将它编码成字节......

...而后将这些字节放入数组中。

而后它会将第一个索引(整数)返回给JavaScript。因此JavaScript能够将字节拉出来并使用它们。

如今,大多数JavaScript方法不知道如何直接使用字节。所以,你须要JavaScript端的一些东西,就你您在WebAssembly端作的那样,它能够将字节转换为更有用的值,好比字符串。

在某些浏览器中,你能够使用TextDecoder和TextEncoder API。或者你能够在你的.js文件中添加辅助函数。例如,像Emscripten这样的工具能够添加编码和解码辅助。

这就是使用JS对象做为WebAssembly内存的第一个好处。WebAssembly和JavaScript能够经过内存直接传递值。

内存泄漏 Memory leaks

正如我在关于内存管理的文章中提到的那样,当你手动管理内存时,你可能会忘记清除它。这可能会致使系统内存不足。

若是WebAssembly模块实例能够直接访问内存,而且在内存离开做用域以前忘记清除内存,则浏览器可能会发生内存泄露。

可是由于内存对象只是一个JavaScript对象,因此它自己被垃圾收集器跟踪(即便它的内容不是)。

这意味着,当内存对象所附的WebAssembly实例离开做用域时,整个内存数组可能会被垃圾收集。

内存隔离 Memory isolation

当人们听到WebAssembly能让你直接访问内存时,它可能会让一些人有点紧张。他们认为一个恶意的WebAssembly模块能够进入内存而且在内存中进行挖掘,但它不该该这样作。但事实并不是如此。

ArrayBuffer的数组范围自然提供了一个边界。这是WebAssembly模块能够直接触摸内存的限制。

它能够直接接触该数组内部的字节,但它不能看到超出此数组边界的任何内容。

例如,内存中的任何其余JS对象(如window)都不能被WebAssembly访问。这对安全性很是重要。

当在WebAssembly中加载或存储时,引擎会执行数组边界检查(array bounds checks)以确保地址位于WebAssembly实例的内存中。

若是代码尝试访问超出界限的地址,则引擎将抛出异常。这种行为保护了其他的内存。

这就是内存导入。在下一篇文章中,咱们将看看另外一种导入更安全的导入方法...table import(导入表格)

相关文章
相关标签/搜索