[譯] 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(導入表格)

相關文章
相關標籤/搜索