7 ms·
Notes on WebAssembly
- dexwiz 4y ago55 votes and no comments. Looks like a lot of people are interested in WASM but no one has anything to say about it.
- rob74 4y agoThere are some comments now... I guess a lot of people (like me) are interested in WASM, but most don't have enough knowledge to say anything "authoritative" about it. When I read "It is a stack machine, no registers", I remembered this other article http://troubles.md/wasm-is-not-a-stack-machine/ http://troubles.md/wasm-is-not-a-stack-machine/ and thought "Ok now, these can't both be right at the same time, right?". But apparently they can - as another comment here states, "WebAssembly is not exactly a stack machine but a stack machine encoding of an instruction tree". To that I say, if I can use the stack as I'm used to from other systems, I don't really care if it's a "real" stack machine. But I'm not really sure of that either...
- lifthrasiir 4y agoI've updated my comment to add more clarification, but let me elaborate a bit more here. If you have the following code: int powi(int n, int m) { int s = 1; while (--m >= 0) s *= n; return s; } The compiled WebAssembly code would look like this (the actual textual format): (func $powi (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (set_local $2 (i32.const 1)) (block $break (loop $continue (br_if $break (i32.ge_s (tee_local $1 (i32.sub (get_local $1) (i32.const 1))) (i32.const 0))) (set_local $2 (i32.mul (get_local $2) (get_local $0))) (br $continue) ) ) (get_local $2) ) Note the clear resemblance between the original code and the compiled binary. The main difference is two branch labels, because WebAssembly distinguishes forward and backward jumps by block types (`block` vs. `loop`). The binary retains all parameters and local variables. When we say WebAssembly is a stack machine, it means that this gets serialized like this: (The textual format allows both forms, while the binary format is a direct translation of the latter.) (func $powi (param $0 i32) (param $1 i32) (result i32) (local $2 i32) i32.const 1 set_local $2 block $break loop $continue get_local $1 i32.const 1 i32.sub tee_local $1 i32.const 0 i32.ge_s br_if $break get_local $2 get_local $0 i32.mul set_local $2 br $continue end end get_local $2 ) In principle you can execute this just like a stack machine with variables, but optimizing implementations will translate this into machine codes, which wouldn't look much like either forms. So the stack machine representation doesn't imply the stack machine execution.
- whizzter 4y agoIirc WASM was initially explicitly designed to be translate-able to Asm.JS (that in turn translated to JS), basically they continued the way Asm.JS had retained backwards compatiblity with JS to either force other browsers to play along in implementing the standard or just look bad in benchmarks. (I think they've relaxed on back-compat now but it was a tool for getting everyone on board and once that had happened it was easier to break it). This is why WASM kind-of-is a stack machine. Basically the opcode sequences should be possible to easily re-translate back into a syntax tree for a back-compat JS generator. This is also why you have these block/loop branches.. it basically is translateable to labelled while loops and if blocks.
- terpimost 4y agoThank you for these notes
- pjmlp 4y ago> Here's a thing that is obvious to me now but I think wasn't obvious when I started. C++ has its own notion of the stack and heap, in that in C++ you can e.g. take the address of something on the stack. This translates to Wasm by C++ stack variables existing in the Wasm-addressable memory, in the same way the C++ stack exists in memory. That memory is totally under the control of the C++ code. Meanwhile, Wasm runtime structures, including the call stack, are separate and are effectively invisible to C++. In summary, C++ memory errors like buffer overflows can still stomp on C++ memory, but that memory is distinct from any Wasm structures such as the call stack, so all a broken Wasm program can do is mess up its own memory, not the host's. And this kids, is why security in WASM still needs to be taken with a grain of salt if any of those modules touch critical data or return values that influence the caller's decisions.
- AndrewDucker 4y agoYes. WASM is secure in that it won't let programs escape. But it runs C and C++ programs which means that it lets them do anything those programs would do - just inside a secure box. If you want your program to be more correct and secure that's then down to you to make sure it is. WASM just makes sure it can't take over the user's PC (or host's, if it's running outside of a browser).
- pjmlp 4y agoWhich is a message that unfortunely many WASM advocates leave out, asserting it is secure all over the board, hence why I tend to point out there are actually some footnotes related to it.
- paulgb 4y agoMaybe I’m missing some nuance here but it’s not clear to me what the omission by wasm advocates is? > And this kids, is why security in WASM still needs to be taken with a grain of salt if any of those modules touch critical data or return values that influence the caller's decisions Isn’t this true of any sandboxed environment? You can trust it not to touch things outside of the sandbox, but any holes you poke to get data in/out need their own verification.
- lifthrasiir 4y ago> It is a stack machine, no registers; instructions generally push and pop 32/64-bit ints and floats onto that stack. One thing to note here is that WebAssembly is not just a stack machine but a stack machine encoding of an instruction tree. You can still execute it as like a stack machine but it doesn't look like a typical stack machine. In particular there are no generic stack manipulation operations at all (`drop` is the sole exception), so it is trivial to convert this encoding back to the instruction tree. This greatly simplifies the validation step. (Edited to clarify that WebAssembly is still a stack machine, just that it lacks usual stack operations.)
- one-more-minute 4y agoI dislike referring to WASM as a "stack machine" for this reason. It is useful to remember that the text format started out as a low-level lisp-y expression tree with local variables and nested control flow. It still basically is that, but with the AST syntactically flattened in a way that looks a bit like a stack machine. (Admittedly, multi-value and block returns have since made it trickier to recover the AST.) Things like Forth or the JVM byte code are true stack machines: all locals can be on the stack, and the stack shape can vary at runtime (which in turn makes validation harder). I seem to be in the minority, but I think wasm is quite different and the distinction is useful to maintain.
- evmar 4y agoThanks for this comment. In a previous draft of the post I had more about this, but I decided to omit it because I didn't have much insight about it beyond some handwaving around how it's just encoding the instructions and the optimizer will do something different. Your comments (this and the other one in this thread) are better than what I would have written, so I learned something today! (Edit: I updated the post to link to your comment.)
- lenkite 4y agoWhere are the great C++ WASM frameworks ? Rust is Ruling the Roost here. Has Figma open-sourced anything yet ?
- Shadonototra 4y agothe entire C/C++ ecosystem are WASM frameworks, thanks to emscripten, you can basically use everything rust is stuck with "rewrite everything to be usable", it can't consume any of that zig on the other hand.. it can, i think it'll have a bright future
- jeroenhd 4y agoRust wasm support seems quite excellent, though? I haven't had too many issues with getting wasm output out of Rust. Emscriptem, though, has been a whole different story. I suppose it depends on what tool chains you're used to using. I don't expect Zig to do any better or worse than Rust in this regard.
- flohofwoe 4y agoZig can (eventually) do better than Rust because it includes the ability to compile C/C++ code to WASM, Rust needs an external C/C++ compiler for this (so you're back to having to deal with Emscripten if you need to embed C/C++ libraries in your Rust project).
- jeroenhd 4y agoThe same is true in reverse, though, you need an external Rust compiler if you include Rust code in your C++ project. Mixing compilers and languages will always cause conflicts, I don't think either Emscripten or Zig will be any different other than that Zig has some backwards compatibility with C/C++.
- azakai 4y agoThey are good for different things, atm. Rust is focused on people writing new code for the Web, and does well there. C++ is focused on porting existing applications, which works well for things like Unity, Photoshop, Google Earth, etc. The reverse cases are sadly not that great atm. If you have a Rust application that uses SDL2 and OpenGL, for example, porting it to the Web is not that easy (you either need to port those APIs to something else, or mix Rust and C to get Emscripten's SDL2 and OpenGL support). And if you want to write new C++ code just for the Web, current bindings solutions are not polished enough. But hopefully all those things will keep improving!
- pmoriarty 4y agoI am concerned that web assembly will mean an end to ad blocking and to a proliferation of malware, as the end user is basically going to be handed an opaque binary blob they can't do much with but execute.
- dotancohen 4y agoThe only way to fight that is to, as a community, refuse to run _all_ wasm that is found to serve ads, or infringe on privacy, or exhibit other malware traits. The only way to do that would be to use browser extensions that disable and report, to disable for other users automatically. But how would we identify the executables? hash? That can be changed trivially. I really fear that wasm brings us 180 degrees from "don't execute anything from the internet" to "all WWW usage is running other peoples' executables".
- deleted 4y ago[deleted]
- jschrf 4y agoThat's already the case! Also, having other people tricked into running other-other people's code with the others' credentials against _your_ code. I think WASM will actually be more secure than the exsting www model. See: POST for an example :) I agree though... there will be bad actors and an ever evolving cat and mouse game
- the_duke 4y agoWasm in the browser can only communicate by going through browser APIs. Most ad / analytics / tracker blocking works by intercepting HTTP requests, so they will work just as well for Wasm code. WASM that uses the regular DOM for rendering also doesn't really change blocking capabilities. The only real issue is visual/selector based blocking when frameworks do their own rendering via canvas, webgl or webgpu. Flutter does this. But doing your own rendering comes with a lot of overhead, both in download sizes, startup time and performance. Applications might do that (with lot's of caveats), but most websites never will. So I'm not that concerned. Wasm is certainly much lower level than JS, but also much higher level than Assembly. It's far from an opaque binary blob. All the minified and partially even obfuscated JS is not that much better.
- modeless 4y ago> Writing to a null pointer is just writing to the memory array at offset zero, as legal as any other write. This seems like a huge design mistake. Is it possible to make dereferencing a null pointer trap in WASM? That's an essential part of debugging C/C++ applications.