WebAssembly / spec

WebAssembly specification, reference interpreter, and test suite.
https://webassembly.github.io/spec/
Other
3.09k stars 438 forks source link

Inline element segment abbreviations omit necessary reftype #1656

Closed tomstuart closed 1 year ago

tomstuart commented 1 year ago

Both cases of a table definition’s inline element segment abbreviation produce syntactically invalid element lists.

Case 1: element list contains element expressions

Problem

e.g. (table $t funcref (elem (ref.func $f) (ref.null func) (ref.func $g))) (from elem.wast) is allowed, but the inline element segment abbreviation would rewrite it into (table $t 3 3 funcref) (elem (table $t) (i32.const 0) (ref.func $f) (ref.null func) (ref.func $g)), which is a syntax error. The rewritten element list is missing a reftype.

Solution

Update the expanded syntax to prefix the element list with the reftype from the abbreviation syntax. The rewritten result for the above example is then (table $t 3 3 funcref) (elem (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func) (ref.func $g)).

Case 2: element list contains function indices

Problem

e.g. (table $t1 funcref (elem $f $g)) (from call_indirect.wast) is allowed, but the inline element segment abbreviation would rewrite it into (table $t1 2 2 funcref) (elem (table $t) (i32.const 0) $f $g), which is a syntax error.

The rewritten element list is missing the ‘func’ keyword; when an element list is written as a sequence of function indices, it must generally be preceded by ‘func’.

Element segment syntax may allow ‘func’ to be omitted (“for backwards compatibility with earlier versions of WebAssembly”) only if the table use is also omitted, but the table use is present in this case.

(A minor point is that in this case it also doesn’t make sense for the abbreviation syntax to use the reftype production. While an element list consisting of a vector of element expressions can use either ‘funcref’ or ‘externref’ as its reference type, an element list consisting of a vector of function indices always uses ‘funcref, so ‘externref’ can never occur here.)

Solution

Update the abbreviation syntax to only allow the ‘funcref’ keyword as the reference type instead of the reftype production. Update the expanded syntax to prefix the element list with the ‘func’ keyword. The rewritten result for the above example is then (table $t1 2 2 funcref) (elem (table $t) (i32.const 0) func $f $g).

rossberg commented 1 year ago

Ah, yes, likely a leftover from Wasm 1.0, when the kernel syntax for element segments was different.