WebAssembly Expert · Lesson 1 · On the house

Validation and the typed stack

How the validator types every instruction, and the polymorphic stack after unreachable. Lesson 1 is free — on the house.

Lessons · WebAssembly Expert · Lesson 1 of 10 · On the house

Validation and the typed stack

How the validator types every instruction, and the polymorphic stack after unreachable.

Illustration for WebAssembly
Lesson 1 is on the house.

Validation runs once, before any code executes. It walks each function with a type stack: every instruction pops the types it needs and pushes its results. A mismatch rejects the whole module.

Each block has a type such as [] -> [i32]. At end, the stack inside the block must match the declared results exactly. Extra values left behind fail validation; there is no implicit drop.

After unreachable, br, br_table or return, the rest of the block is stack-polymorphic: the validator treats the stack as able to supply any type. That is why dead code after return still validates.

Because of this one-pass design, engines compile streaming bytes straight to machine code with no runtime type checks on the operand stack. Validation is what makes that safe.

wasm-validate file.wasm (wabt) or WebAssembly.validate(bytes) reports the first failure; read the offset and use wasm-objdump -d to find the instruction.

polymorphic stack

(module
  (func (export "f") (param $x i32) (result i32)
    local.get $x
    i32.eqz
    if
      i32.const 1
      return
    end
    unreachable
    i64.add
    drop
    i32.const 0))
Match this when you type.

Quiz

Why does `i64.add` after `unreachable` still validate?

Quiz

What happens if a block ends with an extra value on the stack?

Quiz

When does validation run?

Quiz

What does validation allow engines to skip at runtime?

Check

Match the still for: Validation and the typed stack.

Open-book: the answers are on this page. Pass every quiz and check (5) to mark the lesson done. This visit: 0/5.