// validation: array-type imm-operand needs to be "in range"
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array i8))
(func (result eqref)
i32.const66
i32.const77
array.new_fixed 22 ;; type index 2 is the first invalid one
)
)
`), WebAssembly.CompileError, /type index out of range/);
// validation: array-type imm-operand must refer to an array type
assertErrorMessage(() => wasmEvalText(`(module
(type $a (func (param f64) (result f64)))
(func (result eqref)
i32.const66
i32.const77
array.new_fixed $a 2
)
)
`), WebAssembly.CompileError, /not an array type/);
// validation: operands (on stack) must all match ("be compatible with") // the array elem type
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array i32))
(func (result eqref)
f32.const66.6
f64.const77.7
array.new_fixed $a 2
)
)
`), WebAssembly.CompileError, /expression has type f64 but expected i32/);
// validation: number of operands (on stack) must not be less than the // num-of-elems imm-operand
assertNoWarning(() => wasmEvalText(`(module
(type $a (array f32))
(func
f64.const66.6 ;; we won't put this in the array
f32.const77.7
f32.const88.8
array.new_fixed $a 2 ;; use up 88.8 and 77.7 and replace with array
drop ;; dump the array
f64.const99.9
f64.mul ;; check the 66.6 value is still on the stack
drop ;; now should be empty
)
)
`)); // (more)
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array i64))
(func (param i64) (result eqref)
local.get 0
array.new_fixed $a 2
)
)
`), WebAssembly.CompileError, /popping value from empty stack/);
// validation: array-type imm-operand needs to be "in range"
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array i8))
(data $d "1337")
(func (export "newData") (result eqref)
(; offset=0 into data ;) i32.const0
(; size=4 into data ;) i32.const4
array.new_data 2 $d
)
)`), WebAssembly.CompileError, /type index out of range/);
// validation: array-type imm-operand must refer to an array type
assertErrorMessage(() => wasmEvalText(`(module
(type $a (func (param f32) (result f32)))
(data $d "1337")
(func (export "newData") (result eqref)
(; offset=0 into data ;) i32.const0
(; size=4 into data ;) i32.const4
array.new_data $a $d
)
)`), WebAssembly.CompileError, /not an array type/);
// validation: array-type imm-operand must refer to an array of numeric elements
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array eqref))
(data $d "1337")
(func (export "newData") (result eqref)
(; offset=0 into data ;) i32.const0
(; size=4 into data ;) i32.const4
array.new_data $a $d
)
)`), WebAssembly.CompileError,
/element type must be i8\/i16\/i32\/i64\/f32\/f64\/v128/);
// validation: segment index must be "in range"
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array i8))
(data $d "1337")
(func (export "newData") (result eqref)
(; offset=0 into data ;) i32.const0
(; size=4 into data ;) i32.const4
array.new_data $a 1 ;; 1 is the lowest invalid dseg index
)
)`), WebAssembly.CompileError, /segment index is out of range/);
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length array can be created #1
{
let { newData } = wasmEvalText(`(module
(memory 1)
(type $a (array i8))
(data $d (offset (i32.const0)) "1337")
(func (export "newData") (result eqref)
(; offset=0 into data ;) i32.const0
(; size=4 into data ;) i32.const4
array.new_data $a $d
)
)`).exports;
assertErrorMessage(() => {
newData();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length array can be created #2
{
let { newData } = wasmEvalText(`(module
(memory 1)
(type $a (array i8))
(data $d (offset (i32.const0)) "1337")
(func (export "newData") (result eqref)
(; offset=4 into data ;) i32.const4
(; size=0 into data ;) i32.const0
array.new_data $a $d
)
)`).exports;
assertErrorMessage(() => {
newData();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length array can be created #3
{
let { newData } = wasmEvalText(`(module
(memory 1)
(type $a (array i8))
(data $d (offset (i32.const0)) "1337")
(func (export "newData") (result eqref)
(; offset=0 into data ;) i32.const0
(; size=0 into data ;) i32.const0
array.new_data $a $d
)
)`).exports;
let arr = newData();
assertEq(wasmGcArrayLength(arr), 0);
}
// run: range to copy would require OOB read on data segment
{
let { newData } = wasmEvalText(`(module
(type $a (array i8))
(data $d "1337")
(func (export "newData") (result eqref)
(; offset=0 into data ;) i32.const1
(; size=4 into data ;) i32.const4
array.new_data $a $d
)
)`).exports;
assertErrorMessage(() => {
newData();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// run: zero-length copies are allowed
{
let { newData } = wasmEvalText(`(module
(type $a (array i8))
(data $d "1337")
(func (export "newData") (result eqref)
(; offset=0 into data ;) i32.const0
(; size=0 into data ;) i32.const0
array.new_data $a $d
)
)`).exports;
let arr = newData();
assertEq(wasmGcArrayLength(arr), 0);
}
// run: a zero-length copy from the end is allowed
{
let { newData } = wasmEvalText(`(module
(type $a (array i8))
(data $d "1337")
(func (export "newData") (result eqref)
(; offset=4 into data ;) i32.const4
(; size=0 into data ;) i32.const0
array.new_data $a $d
)
)`).exports;
let arr = newData();
assertEq(wasmGcArrayLength(arr), 0);
}
// run: even empty data segments are allowed
{
let { newData } = wasmEvalText(`(module
(type $a (array i8))
(data $d "")
(func (export "newData") (result eqref)
(; offset=0 into data ;) i32.const0
(; size=0 into data ;) i32.const0
array.new_data $a $d
)
)`).exports;
let arr = newData();
assertEq(wasmGcArrayLength(arr), 0);
}
// run: resulting array is as expected
{
let { newData } = wasmEvalText(`(module
(type $a (array i8))
(data $other "\\\\9")
(data $d "1337")
(func (export "newData") (result eqref)
(; offset=0 into data ;) i32.const0
(; size=4 into data ;) i32.const4
array.new_data $a $d
)
)`).exports;
let arr = newData();
assertEq(wasmGcArrayLength(arr), 4);
assertEq(wasmGcReadField(arr, 0), 48+1);
assertEq(wasmGcReadField(arr, 1), 48+3);
assertEq(wasmGcReadField(arr, 2), 48+3);
assertEq(wasmGcReadField(arr, 3), 48+7);
}
// validation: array-type imm-operand needs to be "in range"
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array funcref))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "newElem") (result eqref)
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.new_elem 3 $e
)
)`), WebAssembly.CompileError, /type index out of range/);
// validation: array-type imm-operand must refer to an array type
assertErrorMessage(() => wasmEvalText(`(module
(type $a (func (param i64) (result f64)))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "newElem") (result eqref)
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.new_elem $a $e
)
)`), WebAssembly.CompileError, /not an array type/);
// validation: array-type imm-operand must refer to an array of ref typed // elements
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array f32))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "newElem") (result eqref)
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.new_elem $a $e
)
)`), WebAssembly.CompileError, /element type is not a reftype/);
// validation: destination elem type must be a supertype of src elem type
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array eqref))
(elem $e func $f1)
(func $f1 (export "f1"))
;; The implied copy here is from elem-seg-of-funcrefs to
;; array-of-eqrefs, which must fail, because funcref isn't
;; a subtype of eqref.
(func (export "newElem") (result eqref)
(; offset=0 into elem ;) i32.const0
(; size=0 into elem ;) i32.const0
array.new_elem $a $e
)
)`), WebAssembly.CompileError, /incompatible element types/);
// validation: segment index must be "in range"
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array funcref))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "newElem") (result eqref)
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.new_elem $a 1 ;; 1 is the lowest invalid eseg index
)
)`), WebAssembly.CompileError, /segment index is out of range/);
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length array can be created #1
{
let { newElem } = wasmEvalText(`(module
(table 4 funcref)
(type $a (array funcref))
(elem $e (offset (i32.const0)) func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "newElem") (result eqref)
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.new_elem $a $e
)
)`).exports;
assertErrorMessage(() => {
newElem();
}, WebAssembly.RuntimeError, /index out of bounds/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length array can be created #2
{
let { newElem } = wasmEvalText(`(module
(table 4 funcref)
(type $a (array funcref))
(elem $e (offset (i32.const0)) func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "newElem") (result eqref)
(; offset=4 into elem ;) i32.const4
(; size=0 into elem ;) i32.const0
array.new_elem $a $e
)
)`).exports;
assertErrorMessage(() => {
newElem();
}, WebAssembly.RuntimeError, /index out of bounds/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length array can be created #3
{
let { newElem } = wasmEvalText(`(module
(table 4 funcref)
(type $a (array funcref))
(elem $e (offset (i32.const0)) func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "newElem") (result eqref)
(; offset=0 into elem ;) i32.const0
(; size=0 into elem ;) i32.const0
array.new_elem $a $e
)
)`).exports;
let arr = newElem();
assertEq(wasmGcArrayLength(arr), 0);
}
// run: range to copy would require OOB read on elem segment
{
let { newElem } = wasmEvalText(`(module
(type $a (array funcref))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "newElem") (result eqref)
(; offset=0 into elem ;) i32.const1
(; size=4 into elem ;) i32.const4
array.new_elem $a $e
)
)`).exports;
assertErrorMessage(() => {
newElem();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// validation: array-type imm-operand needs to be "in range"
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array i8))
(data $d "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=4 elements ;) i32.const4
array.init_data 2 $d
)
)`), WebAssembly.CompileError, /type index out of range/);
// validation: array-type imm-operand must refer to an array type
assertErrorMessage(() => wasmEvalText(`(module
(type $a (func (param f32) (result f32)))
(data $d "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=4 elements ;) i32.const4
array.init_data $a $d
)
)`), WebAssembly.CompileError, /not an array type/);
// validation: array-type imm-operand must refer to an array of numeric elements
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array eqref))
(data $d "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=4 elements ;) i32.const4
array.init_data $a $d
)
)`), WebAssembly.CompileError, /element type must be i8\/i16\/i32\/i64\/f32\/f64\/v128/);
// validation: array-type imm-operand must be mutable
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array i8))
(data $d "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=4 elements ;) i32.const4
array.init_data $a $d
)
)`), WebAssembly.CompileError,
/destination array is not mutable/);
// validation: segment index must be "in range"
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array (mut i8)))
(data $d "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=4 elements ;) i32.const4
array.init_data $a 1 ;; 1 is the lowest invalid dseg index
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`), WebAssembly.CompileError, /segment index is out of range/);
// run: array must not be null
{
let { initData } = wasmEvalText(`(module
(type $a (array (mut i8)))
(data $d "1337")
(func (export "initData")
(; array to init ;) (ref.null $a)
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=4 elements ;) i32.const4
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
assertErrorMessage(() => {
initData();
}, WebAssembly.RuntimeError, /dereferencing null pointer/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length init can be performed #1
{
let { initData } = wasmEvalText(`(module
(memory 1)
(type $a (array (mut i8)))
(data $d (offset (i32.const0)) "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=4 elements ;) i32.const4
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
assertErrorMessage(() => {
initData();
}, WebAssembly.RuntimeError, /index out of bounds/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length init can be performed #2
{
let { initData } = wasmEvalText(`(module
(memory 1)
(type $a (array (mut i8)))
(data $d (offset (i32.const0)) "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=4 into data ;) i32.const4
(; size=0 elements ;) i32.const0
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
assertErrorMessage(() => {
initData();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length init can be performed #3
{
let { initData } = wasmEvalText(`(module
(memory 1)
(type $a (array (mut i8)))
(data $d (offset (i32.const0)) "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=0 elements ;) i32.const0
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
initData();
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length init can be performed #4
{
let { initData } = wasmEvalText(`(module
(type $a (array (mut i8)))
(data $d "1337")
(func (export "initData")
data.drop $d
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=4 elements ;) i32.const4
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
assertErrorMessage(() => {
initData();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length init can be performed #5
{
let { initData } = wasmEvalText(`(module
(type $a (array (mut i8)))
(data $d "1337")
(func (export "initData")
data.drop $d
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=0 elements ;) i32.const0
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
initData();
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length init can be performed #6
{
let { initData } = wasmEvalText(`(module
(memory 1)
(type $a (array (mut i8)))
(data $d "1337")
(func (export "initData")
data.drop $d
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=4 into array ;) i32.const4
(; offset=0 into data ;) i32.const0
(; size=0 elements ;) i32.const0
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
initData();
}
// run: range to copy would require OOB read on data segment #1
{
let { initData } = wasmEvalText(`(module
(type $a (array (mut i8)))
(data $d "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=1 into data ;) i32.const1
(; size=4 elements ;) i32.const4
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
assertErrorMessage(() => {
initData();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// run: range to copy would require OOB read on data segment #2
{
let { initData } = wasmEvalText(`(module
(type $a (array (mut i16)))
(data $d "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=1 into data ;) i32.const1
(; size=2 elements ;) i32.const2 ;; still 4 bytes
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
assertErrorMessage(() => {
initData();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// run: range to copy would require OOB write on array #1
{
let { initData } = wasmEvalText(`(module
(type $a (array (mut i8)))
(data $d "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=1 into array ;) i32.const1
(; offset=0 into data ;) i32.const0
(; size=4 elements ;) i32.const4
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
assertErrorMessage(() => {
initData();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// run: range to copy would require OOB write on array #2
{
let { initData } = wasmEvalText(`(module
(type $a (array (mut i16)))
(data $d "1337")
(func (export "initData")
(; array to init ;) (array.new_default $a (i32.const2))
(; offset=1 into array ;) i32.const1
(; offset=0 into data ;) i32.const0
(; size=4 elements ;) i32.const2
array.init_data $a $d
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
assertErrorMessage(() => {
initData();
},WebAssembly.RuntimeError, /index out of bounds/);
}
(; array to init ;) local.get $arr
(; offset=0 into array ;) i32.const0
(; offset=0 into data ;) i32.const0
(; size=0 elements ;) i32.const0
array.init_data $a $d
local.get $arr
)
(func data.drop 0) ;; force write of data count section, see https://github.com/bytecodealliance/wasm-tools/pull/1194
)`).exports;
let arr = initData();
assertEq(wasmGcArrayLength(arr), 0);
}
// validation: array-type imm-operand needs to be "in range"
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array (mut funcref)))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.init_elem 4 $e
)
)`), WebAssembly.CompileError, /type index out of range/);
// validation: array-type imm-operand must refer to an array type
assertErrorMessage(() => wasmEvalText(`(module
(type $a (func (param i64) (result f64)))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.init_elem $a $e
)
)`), WebAssembly.CompileError, /not an array type/);
// validation: array-type imm-operand must refer to an array of ref typed // elements
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array (mut f32)))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.init_elem $a $e
)
)`), WebAssembly.CompileError, /element type is not a reftype/);
// validation: array-type imm-operand must be mutable
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array funcref))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.init_elem $a $e
)
)`), WebAssembly.CompileError, /destination array is not mutable/);
// validation: destination elem type must be a supertype of src elem type
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array (mut eqref)))
(elem $e func $f1)
(func $f1 (export "f1"))
;; The copy here is from elem-seg-of-funcrefs to
;; array-of-eqrefs, which must fail, because funcref isn't
;; a subtype of eqref.
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.init_elem $a $e
)
)`), WebAssembly.CompileError, /incompatible element types/);
// validation: segment index must be "in range"
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array (mut funcref)))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.init_elem $a 1 ;; 1 is the lowest invalid eseg index
)
)`), WebAssembly.CompileError, /segment index is out of range/);
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length array can be created #1
{
let { initElem } = wasmEvalText(`(module
(table 4 funcref)
(type $a (array (mut funcref)))
(elem $e (offset (i32.const0)) func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.init_elem $a $e
)
)`).exports;
assertErrorMessage(() => {
initElem();
}, WebAssembly.RuntimeError, /index out of bounds/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length array can be created #2
{
let { initElem } = wasmEvalText(`(module
(table 4 funcref)
(type $a (array (mut funcref)))
(elem $e (offset (i32.const0)) func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=4 into elem ;) i32.const4
(; size=0 into elem ;) i32.const0
array.init_elem $a $e
)
)`).exports;
assertErrorMessage(() => {
initElem();
}, WebAssembly.RuntimeError, /index out of bounds/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length array can be created #3
{
let { initElem } = wasmEvalText(`(module
(table 4 funcref)
(type $a (array (mut funcref)))
(elem $e (offset (i32.const0)) func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const0
(; size=0 into elem ;) i32.const0
array.init_elem $a $e
)
)`).exports;
initElem();
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length init can be performed #4
{
let { initElem } = wasmEvalText(`(module
(type $a (array (mut funcref)))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
elem.drop $e
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.init_elem $a $e
)
)`).exports;
assertErrorMessage(() => {
initElem();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length init can be performed #5
{
let { initElem } = wasmEvalText(`(module
(type $a (array (mut funcref)))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
elem.drop $e
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const0
array.init_elem $a $e
)
)`).exports;
initElem();
}
// run: if segment is "already used" (active, or passive that has subsequently // been dropped), then only a zero length init can be performed #6
{
let { initElem } = wasmEvalText(`(module
(type $a (array (mut funcref)))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
elem.drop $e
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const4
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const0
array.init_elem $a $e
)
)`).exports;
initElem();
}
// run: range to copy would require OOB read on elem segment
{
let { initElem } = wasmEvalText(`(module
(type $a (array (mut funcref)))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const0
(; offset=0 into elem ;) i32.const1
(; size=4 into elem ;) i32.const4
array.init_elem $a $e
)
)`).exports;
assertErrorMessage(() => {
initElem();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// run: range to copy would require OOB write on array
{
let { initElem } = wasmEvalText(`(module
(type $a (array (mut funcref)))
(elem $e func $f1 $f2 $f3 $f4)
(func $f1 (export "f1"))
(func $f2 (export "f2"))
(func $f3 (export "f3"))
(func $f4 (export "f4"))
(func (export "initElem")
(; array to init ;) (array.new_default $a (i32.const4))
(; offset=0 into array ;) i32.const1
(; offset=0 into elem ;) i32.const0
(; size=4 into elem ;) i32.const4
array.init_elem $a $e
)
)`).exports;
assertErrorMessage(() => {
initElem();
},WebAssembly.RuntimeError, /index out of bounds/);
}
// validation: dest array must be mutable
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array i32))
(func (param eqref)
(array.copy $a $a (local.get 0) (i32.const1)
(local.get 0) (i32.const2) (i32.const3))
)
)
`), WebAssembly.CompileError, /array is not mutable/);
// validation: src and dest arrays must have compatible element types #1
assertErrorMessage(() => wasmEvalText(`(module
(type $a32 (array (mut i32)))
(type $a8 (array i8))
(func (param eqref)
(array.copy $a32 $a8 (local.get 0) (i32.const1)
(local.get 0) (i32.const2) (i32.const3))
)
)
`), WebAssembly.CompileError, /incompatible element types/);
// validation: src and dest arrays must have compatible element types #2
assertErrorMessage(() => wasmEvalText(`(module
(type $a64 (array (mut i64)))
(type $aER (array eqref))
(func (param eqref)
(array.copy $a64 $aER (local.get 0) (i32.const1)
(local.get 0) (i32.const2) (i32.const3))
)
)
`), WebAssembly.CompileError, /incompatible element types/);
// validation: src and dest arrays must have compatible element types #3 // // We can only copy from a child (sub) reftype to a parent (super) reftype [or // to the same reftype.] Here, we have an array of eqref and an array of // arrays. An array is a child type of eqref, so it's invalid to try and copy // eqrefs into the array of arrays.
assertErrorMessage(() => wasmEvalText(`(module
(type $ty (array i32))
(type $child (array (mut (ref $ty))))
(type $parent (array (mut eqref)))
(func (param (ref null $child) (ref null $parent))
;; implied copy from parent to child -> not allowed
(array.copy $child $parent (local.get 1) (i32.const1)
(local.get 0) (i32.const2) (i32.const3))
)
)
`), WebAssembly.CompileError, /incompatible element types/);
// dst overrun, wants to write [5, 6]
assertErrorMessage(() => {
arrayCopy(exp1TO, 5, exp2TO, 1, 2);
},WebAssembly.RuntimeError, /index out of bounds/);
// dst overrun, wants to write [7, 8]
assertErrorMessage(() => {
arrayCopy(exp1TO, 7, exp2TO, 1, 2);
},WebAssembly.RuntimeError, /index out of bounds/);
// dst zero-len overrun, wants to write no elements, but starting at 9
assertErrorMessage(() => {
arrayCopy(exp1TO, 9, exp2TO, 1, 0);
},WebAssembly.RuntimeError, /index out of bounds/);
// src overrun, wants to read [5, 6]
assertErrorMessage(() => {
arrayCopy(exp1TO, 1, exp2TO, 5, 2);
},WebAssembly.RuntimeError, /index out of bounds/);
// src overrun, wants to read [7, 8]
assertErrorMessage(() => {
arrayCopy(exp1TO, 1, exp2TO, 7, 2);
},WebAssembly.RuntimeError, /index out of bounds/);
// src zero-len overrun, wants to read no elements, but starting at 9
assertErrorMessage(() => {
arrayCopy(exp1TO, 1, exp2TO, 9, 0);
},WebAssembly.RuntimeError, /index out of bounds/);
}
// validation: array must be mutable
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array i32))
(func
(array.new_default $a (i32.const8))
i32.const0
i32.const123
i32.const8
array.fill $a
)
)
`), WebAssembly.CompileError, /array is not mutable/);
// validation: value must be compatible with array element type #1
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array (mut i32)))
(func
(array.new_default $a (i32.const8))
i32.const0
i64.const123
i32.const8
array.fill $a
)
)
`), WebAssembly.CompileError, /type mismatch/);
// validation: value must be compatible with array element type #2
assertErrorMessage(() => wasmEvalText(`(module
(type $a (array (mut eqref)))
(func
(array.new_default $a (i32.const8))
i32.const0
ref.null any
i32.const8
array.fill $a
)
)
`), WebAssembly.CompileError, /type mismatch/);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.