summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/wasm-s-parser.cpp6
-rw-r--r--src/wasm/wasm-validator.cpp1
-rw-r--r--test/example/c-api-kitchen-sink.c3
-rw-r--r--test/spec/array.wast146
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"
+)