This is the 2nd article in a 3-part series:
- Memory in WebAssembly (and why it’s safer than you think)
- WebAssembly table imports… what are they?
What is the memory object?
When a WebAssembly module is instantiated, it needs a memory object. You can either create a new
WebAssembly.Memory and pass that object in. Or, if you don’t, a memory object will be created and attached to the instance automatically.
The indexes to the array can be treated as though they were memory addresses. And if you need more memory later, you can do something called growing to make the array larger.
- makes it easy to pass values between JS and WebAssembly
- helps make the memory management safe
Passing values between JS and WebAssembly
Instead of using a memory address, they use an array index to access each box.
For example, the WebAssembly could put a string in memory. It would encode it into bytes…
…and then put those bytes in the array.
Making memory access safer
As I mentioned in the article on memory management, when you manage your own memory you may forget to clear it out. This can cause the system to run out of memory.
If a WebAssembly module instance had direct access to memory, and if it forgot to clear out that memory before it went out of scope, then the browser could leak memory.
That means that when the WebAssembly instance that the memory object is attached to goes out of scope, this whole memory array can just be garbage collected.
When people hear that WebAssembly gives you direct access to memory, it can make them a little nervous. They think that a malicious WebAssembly module could go in and dig around in memory it shouldn’t be able to. But that isn’t the case.
The bounds of the ArrayBuffer provide a boundary. It’s a limit to what memory the WebAssembly module can touch directly.
It can directly touch the bytes that are inside of this array but it can’t see anything that’s outside the bounds of this array.
For example, any other JS objects that are in memory, like the window global, aren’t accessible to WebAssembly. That’s really important for security.
Whenever there’s a load or a store in WebAssembly, the engine does an array bounds checks to make sure that the address is inside the WebAssembly instance’s memory.
If the code tries to access an out-of-bounds address, the engine will throw an exception. This protects the rest of the memory.
So that’s the memory import. In the next article, we’ll look at another kind of import that makes things safer… the table import.
About Lin Clark
Lin works in Advanced Development at Mozilla, with a focus on Rust and WebAssembly.