diff options
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 1 | ||||
-rw-r--r-- | test/example/c-api-kitchen-sink.c | 3 | ||||
-rw-r--r-- | test/spec/array.wast | 146 |
4 files changed, 154 insertions, 2 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 7182860ed..edf8ec6f0 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -694,7 +694,11 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { return builder.getTempRefType(typeIndices[name], Nullable); } else if (String::isNumber(name)) { // TODO: Support non-nullable types - return builder.getTempRefType(atoi(name), Nullable); + size_t index = atoi(name); + if (index >= numTypes) { + throw ParseException("invalid type index", elem.line, elem.col); + } + return builder.getTempRefType(index, Nullable); } else { // TODO: Support non-nullable types return Type(stringToHeapType(name), Nullable); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 7e9c30c77..1a5894343 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2491,6 +2491,7 @@ void FunctionValidator::visitArraySet(ArraySet* curr) { element.type, curr, "array.set must have the proper type"); + shouldBeTrue(element.mutable_, curr, "array.set type must be mutable"); } void FunctionValidator::visitArrayLen(ArrayLen* curr) { diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 0f9c33f5d..cbf795e5c 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -261,7 +261,8 @@ void test_features() { printf("BinaryenFeatureMultivalue: %d\n", BinaryenFeatureMultivalue()); printf("BinaryenFeatureGC: %d\n", BinaryenFeatureGC()); printf("BinaryenFeatureMemory64: %d\n", BinaryenFeatureMemory64()); - printf("BinaryenFeatureTypedFunctionReferences: %d\n", BinaryenFeatureTypedFunctionReferences()); + printf("BinaryenFeatureTypedFunctionReferences: %d\n", + BinaryenFeatureTypedFunctionReferences()); printf("BinaryenFeatureAll: %d\n", BinaryenFeatureAll()); } diff --git a/test/spec/array.wast b/test/spec/array.wast new file mode 100644 index 000000000..243431319 --- /dev/null +++ b/test/spec/array.wast @@ -0,0 +1,146 @@ +;; XXX BINARYEN: rename array.new_default => array.new_default_with_rtt + +;; Type syntax + +(module + (type (array i8)) + (type (array i16)) + (type (array i32)) + (type (array i64)) + (type (array f32)) + (type (array f64)) + (type (array anyref)) + (type (array (ref data))) + (type (array (ref 0))) + (type (array (ref null 1))) + (type (array (rtt 1))) + (type (array (rtt 10 1))) + (type (array (mut i8))) + (type (array (mut i16))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut anyref))) + (type (array (mut (ref data)))) + (type (array (mut (ref 0)))) + (type (array (mut (ref null i31)))) + (type (array (mut (rtt 0)))) + (type (array (mut (rtt 10 0)))) +) + + +(assert_invalid + (module + (type (array (mut (ref null 10)))) + ) + "unknown type" +) + + +;; Binding structure + +(module + (type $s0 (array (ref $s1))) + (type $s1 (array (ref $s0))) + + (func (param (ref $forward))) + + (type $forward (array i32)) +) + +(assert_invalid + (module (type (array (ref 1)))) + "unknown type" +) +(assert_invalid + (module (type (array (mut (ref 1))))) + "unknown type" +) + + +;; Basic instructions + +(module + (type $vec (array f32)) + (type $mvec (array (mut f32))) + + (func $get (param $i i32) (param $v (ref $vec)) (result f32) + (array.get $vec (local.get $v) (local.get $i)) + ) + (func (export "get") (param $i i32) (result f32) + (call $get (local.get $i) + (array.new_default_with_rtt $vec (i32.const 3) (rtt.canon $vec)) + ) + ) + + (func $set_get (param $i i32) (param $v (ref $mvec)) (param $y f32) (result f32) + (array.set $mvec (local.get $v) (local.get $i) (local.get $y)) + (array.get $mvec (local.get $v) (local.get $i)) + ) + (func (export "set_get") (param $i i32) (param $y f32) (result f32) + (call $set_get (local.get $i) + (array.new_default_with_rtt $mvec (i32.const 3) (rtt.canon $mvec)) + (local.get $y) + ) + ) + + (func $len (param $v (ref $vec)) (result i32) + (array.len $vec (local.get $v)) + ) + (func (export "len") (result i32) + (call $len (array.new_default_with_rtt $vec (i32.const 3) (rtt.canon $vec))) + ) +) + +(assert_return (invoke "get" (i32.const 0)) (f32.const 0)) +(assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7)) +(assert_return (invoke "len") (i32.const 3)) + +(assert_trap (invoke "get" (i32.const 10)) "out of bounds") +(assert_trap (invoke "set_get" (i32.const 10) (f32.const 7)) "out of bounds") + +(assert_invalid + (module + (type $a (array i64)) + (func (export "array.set-immutable") (param $a (ref $a)) + (array.set $a (local.get $a) (i32.const 0) (i64.const 1)) + ) + ) + "array is immutable" +) + + +;; Null dereference + +(module + (type $t (array (mut i32))) + (func (export "array.get-null") + (local (ref null $t)) (drop (array.get $t (local.get 0) (i32.const 0))) + ) + (func (export "array.set-null") + (local (ref null $t)) (array.set $t (local.get 0) (i32.const 0) (i32.const 0)) + ) +) + +(assert_trap (invoke "array.get-null") "null array") +(assert_trap (invoke "array.set-null") "null array") + +(assert_invalid + (module + (type $t (array i32)) + (func (export "array.new-null") + (local (ref null (rtt $t))) (drop (array.new_default_with_rtt $t (i32.const 1) (i32.const 3) (local.get 0))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type $t (array (mut i32))) + (func (export "array.new_default_with_rtt-null") + (local (ref null (rtt $t))) (drop (array.new_default_with_rtt $t (i32.const 3) (local.get 0))) + ) + ) + "type mismatch" +) |