From 134874911e2ddb8af0d5fa1ccc5993f83425be1e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 17 May 2022 08:48:44 -0700 Subject: [PATCH] Add more tests exercising the component model This is mostly adding tests for invalid constructs in the component model to ensure that wasmparser generates the right error in the future during refactorings. Additionally some miscellaneous items are fixed along the way: * Some dead code in wasmparser was removed * The type check error message for component functions was fixed when results mismatch. * The `wast` crate is a little more lax about `alias` statements that are clearly out of bounds (lets `wasmparser` generate the error instead). * Parsing support for `(component quote "...")` was added --- coverage.sh | 25 --- crates/wasmparser/src/binary_reader.rs | 25 --- crates/wasmparser/src/validator/component.rs | 4 +- crates/wast/src/component/resolve.rs | 9 + crates/wast/src/wast.rs | 25 ++- tests/local/component-model/adapt.wast | 161 ++++++++++++++ tests/local/component-model/alias.wast | 16 ++ tests/local/component-model/export.wast | 42 ++++ tests/local/component-model/import.wast | 34 +++ tests/local/component-model/instantiate.wast | 220 +++++++++++++++++++ tests/local/component-model/intertypes.wast | 66 ++++++ tests/local/component-model/invalid.wast | 18 +- tests/local/component-model/start.wast | 55 +++++ tests/local/component-model/types.wast | 158 +++++++++++++ tests/local/component-model/very-nested.wast | 166 ++++++++++++++ tests/roundtrip.rs | 2 +- 16 files changed, 954 insertions(+), 72 deletions(-) delete mode 100644 coverage.sh create mode 100644 tests/local/component-model/start.wast diff --git a/coverage.sh b/coverage.sh deleted file mode 100644 index 305e27c28a..0000000000 --- a/coverage.sh +++ /dev/null @@ -1,25 +0,0 @@ -set -ex - -cargo test --test roundtrip - -rm -rf cov -mkdir cov - -export LLVM_PROFILE_FILE="`pwd`/cov/coverage-%m.profraw" -export RUSTFLAGS="-C instrument-coverage" -export CARGO_TARGET_DIR=`pwd`/target/coverage - -cargo test --test roundtrip - -llvm-profdata merge -sparse cov/coverage-*.profraw -o cov/coverage.profdata -llvm-cov show -Xdemangler=rustfilt \ - ./target/coverage/debug/deps/roundtrip-92d636af98ebdc72 \ - --format=html \ - --ignore-filename-regex='/.cargo/registry' \ - --ignore-filename-regex='/rustc/' \ - --instr-profile=cov/coverage.profdata \ - --show-line-counts-or-regions \ - --show-instantiations \ - --show-regions \ - --output-dir=cov - diff --git a/crates/wasmparser/src/binary_reader.rs b/crates/wasmparser/src/binary_reader.rs index 142fc39240..5d7d361853 100644 --- a/crates/wasmparser/src/binary_reader.rs +++ b/crates/wasmparser/src/binary_reader.rs @@ -924,31 +924,6 @@ impl<'a> BinaryReader<'a> { Ok(b) } - /// Advances the `BinaryReader` up to two bytes to parse a variable - /// length integer as a `u8`. - /// - /// # Errors - /// - /// If `BinaryReader` has less than one or two bytes remaining, or the - /// variable integer is larger than eight bits. - pub fn read_var_u8(&mut self) -> Result { - // Optimization for single byte i32. - let byte = self.read_u8()?; - if (byte & 0x80) == 0 { - return Ok(byte); - } - - let next = self.read_u8()? as u32; - let result: u32 = (next << 7) | (byte & 0x7F) as u32; - if result >= 0x100 { - return Err(BinaryReaderError::new( - "invalid var_u8: integer representation too long", - self.original_position() - 1, - )); - } - Ok(result as u8) - } - /// Advances the `BinaryReader` up to four bytes to parse a variable /// length integer as a `u32`. /// diff --git a/crates/wasmparser/src/validator/component.rs b/crates/wasmparser/src/validator/component.rs index c1a3753b62..30545b0795 100644 --- a/crates/wasmparser/src/validator/component.rs +++ b/crates/wasmparser/src/validator/component.rs @@ -183,9 +183,7 @@ impl ComponentState { // export signature let (params, results) = ty.lower(types, false); - if core_ty.params.as_ref() != params.as_slice() - || core_ty.returns.as_ref() != results.as_slice() - { + if core_ty.params.as_ref() != params.as_slice() { return Err(BinaryReaderError::new( format!("lowered parameter types `{:?}` do not match parameter types `{:?}` of core function {func_index}", params.as_slice(), core_ty.params), offset, diff --git a/crates/wast/src/component/resolve.rs b/crates/wast/src/component/resolve.rs index 0d79ee78c2..faa058f479 100644 --- a/crates/wast/src/component/resolve.rs +++ b/crates/wast/src/component/resolve.rs @@ -222,6 +222,15 @@ fn resolve_alias<'a, 'b>( export: _, } => resolve_ns(instance, Ns::Instance, resolve_stack), AliasTarget::Outer { outer, index } => { + // Short-circuit when both indices are already resolved as this + // helps to write tests for invalid modules where wasmparser should + // be the one returning the error. + if let Index::Num(..) = outer { + if let Index::Num(..) = index { + return Ok(()); + } + } + // Resolve `outer`, and compute the depth at which to look up // `index`. let depth = match outer { diff --git a/crates/wast/src/wast.rs b/crates/wast/src/wast.rs index 4b409d8c2b..f732674b92 100644 --- a/crates/wast/src/wast.rs +++ b/crates/wast/src/wast.rs @@ -109,7 +109,8 @@ impl WastDirective<'_> { match self { WastDirective::Wat(QuoteWat::Wat(Wat::Module(m))) => m.span, WastDirective::Wat(QuoteWat::Wat(Wat::Component(c))) => c.span, - WastDirective::Wat(QuoteWat::Quote(span, _)) => *span, + WastDirective::Wat(QuoteWat::QuoteModule(span, _)) => *span, + WastDirective::Wat(QuoteWat::QuoteComponent(span, _)) => *span, WastDirective::AssertMalformed { span, .. } | WastDirective::Register { span, .. } | WastDirective::AssertTrap { span, .. } @@ -271,16 +272,18 @@ impl<'a> Parse<'a> for WastInvoke<'a> { #[derive(Debug)] pub enum QuoteWat<'a> { Wat(Wat<'a>), - Quote(Span, Vec<(Span, &'a [u8])>), + QuoteModule(Span, Vec<(Span, &'a [u8])>), + QuoteComponent(Span, Vec<(Span, &'a [u8])>), } impl QuoteWat<'_> { /// Encodes this module to bytes, either by encoding the module directly or /// parsing the contents and then encoding it. pub fn encode(&mut self) -> Result, Error> { - let source = match self { + let (source, prefix) = match self { QuoteWat::Wat(m) => return m.encode(), - QuoteWat::Quote(_, source) => source, + QuoteWat::QuoteModule(_, source) => (source, None), + QuoteWat::QuoteComponent(_, source) => (source, Some("(component")), }; let mut ret = String::new(); for (span, src) in source { @@ -292,6 +295,10 @@ impl QuoteWat<'_> { } ret.push_str(" "); } + if let Some(prefix) = prefix { + ret.insert_str(0, prefix); + ret.push_str(")"); + } let buf = ParseBuffer::new(&ret)?; let mut wat = parser::parse::>(&buf)?; wat.encode() @@ -301,7 +308,13 @@ impl QuoteWat<'_> { impl<'a> Parse<'a> for QuoteWat<'a> { fn parse(parser: Parser<'a>) -> Result { if parser.peek2::() { - parser.parse::()?; + let ctor = if parser.peek::() { + parser.parse::()?; + QuoteWat::QuoteComponent + } else { + parser.parse::()?; + QuoteWat::QuoteModule + }; let span = parser.parse::()?.0; let mut src = Vec::new(); while !parser.is_empty() { @@ -309,7 +322,7 @@ impl<'a> Parse<'a> for QuoteWat<'a> { let string = parser.parse()?; src.push((span, string)); } - Ok(QuoteWat::Quote(span, src)) + Ok(ctor(span, src)) } else { Ok(QuoteWat::Wat(parse_wat(parser)?)) } diff --git a/tests/local/component-model/adapt.wast b/tests/local/component-model/adapt.wast index 38c87b3d24..3b0cfdf0e1 100644 --- a/tests/local/component-model/adapt.wast +++ b/tests/local/component-model/adapt.wast @@ -55,3 +55,164 @@ (canon.lift (func (param string)) string=latin1+utf16 (into $libc) (func $my_instance "log-compact-utf16"))) ) + +(assert_invalid + (component + (import "" (func $f)) + (func (canon.lower string=utf8 string=utf16 (func $f))) + ) + "canonical option `utf8` conflicts with option `utf16`") + +(assert_invalid + (component + (import "" (func $f)) + (func (canon.lower string=utf8 string=latin1+utf16 (func $f))) + ) + "canonical option `utf8` conflicts with option `compact-utf16`") + +(assert_invalid + (component + (import "" (func $f)) + (func (canon.lower string=utf16 string=latin1+utf16 (func $f))) + ) + "canonical option `utf16` conflicts with option `compact-utf16`") + +(assert_invalid + (component + (import "" (func $f)) + (func (canon.lower (into 0) (func $f))) + ) + "instance index out of bounds") + +(assert_invalid + (component + (import "" (func $f)) + (import "i" (instance $i)) + (func (canon.lower (into $i) (func $f))) + ) + "not a module instance") + +(assert_invalid + (component + (import "" (func $f)) + (module $m) + (instance $i (instantiate (module $m))) + (func (canon.lower (into $i) (into $i) (func $f))) + ) + "`into` is specified more than once") + +(assert_invalid + (component + (module $m + (func (export "") (param i32 i32)) + ) + (instance $i (instantiate (module $m))) + (func (canon.lift (func (param (list u8))) (func $i ""))) + ) + "canonical option `into` is required") + +(assert_invalid + (component + (module $m + (func (export "") (param i32 i32)) + ) + (instance $i (instantiate (module $m))) + (func (canon.lift (func (param (list u8))) (into $i) (func $i ""))) + ) + "does not export a memory") + +(assert_invalid + (component + (module $m + (func (export "") (param i32 i32)) + (memory (export "memory") 0) + ) + (instance $i (instantiate (module $m))) + (func (canon.lift (func (param (list u8))) (into $i) (func $i ""))) + ) + "does not export a function named `canonical_abi_realloc`") + +(assert_invalid + (component + (module $m + (func (export "") (param i32 i32)) + (memory (export "memory") 0) + (func (export "canonical_abi_realloc")) + ) + (instance $i (instantiate (module $m))) + (func (canon.lift (func (param (list u8))) (into $i) (func $i ""))) + ) + "wrong signature") + +(assert_invalid + (component + (module $m + (func (export "") (param i32 i32)) + (memory (export "memory") 0) + (func (export "canonical_abi_realloc") (param i32 i32 i32 i32) (result i32) + unreachable) + ) + (instance $i (instantiate (module $m))) + (func (canon.lift (func (param (list u8))) (into $i) (func $i ""))) + ) + "does not export a function named `canonical_abi_free`") + +(assert_invalid + (component + (module $m + (func (export "") (param i32 i32)) + (memory (export "memory") 0) + (func (export "canonical_abi_realloc") (param i32 i32 i32 i32) (result i32) + unreachable) + (func (export "canonical_abi_free")) + ) + (instance $i (instantiate (module $m))) + (func (canon.lift (func (param (list u8))) (into $i) (func $i ""))) + ) + "wrong signature") + +(assert_invalid + (component + (module $m + (func (export "")) + ) + (instance $i (instantiate (module $m))) + (func (canon.lower (func $i ""))) + ) + "not a component function") + +(assert_invalid + (component + (module $m (func (export "foo") (param i32))) + (instance $i (instantiate (module $m))) + (func (export "foo") + (canon.lift (func) (func $i "foo"))) + ) + "lowered parameter types `[]` do not match parameter types `[I32]`") + +(assert_invalid + (component + (module $m (func (export "foo") (result i32))) + (instance $i (instantiate (module $m))) + (func (export "foo") + (canon.lift (func) (func $i "foo"))) + ) + "lowered result types `[]` do not match result types `[I32]`") + +(assert_invalid + (component + (type $f string) + (module $m (func (export "foo"))) + (instance $i (instantiate (module $m))) + (func (export "foo") + (canon.lift (type $f) (func $i "foo"))) + ) + "not a function type") + +(assert_invalid + (component + (import "" (func $f)) + (func (export "foo") + (canon.lift (func) (func $f))) + ) + "not a core WebAssembly function") diff --git a/tests/local/component-model/alias.wast b/tests/local/component-model/alias.wast index 32a9b0f6dd..bd308754ec 100644 --- a/tests/local/component-model/alias.wast +++ b/tests/local/component-model/alias.wast @@ -266,3 +266,19 @@ (alias outer $C $m (component $target)) (export "v" (component $target)) ) + +(assert_invalid + (component (alias outer 100 0 (module))) + "invalid outer alias count of 100") + +(assert_invalid + (component (alias outer 0 0 (module))) + "index out of bounds") + +(assert_invalid + (component (alias outer 100 0 (component))) + "invalid outer alias count of 100") + +(assert_invalid + (component (alias outer 0 0 (component))) + "index out of bounds") diff --git a/tests/local/component-model/export.wast b/tests/local/component-model/export.wast index 00b8d96ae1..1f43f3901e 100644 --- a/tests/local/component-model/export.wast +++ b/tests/local/component-model/export.wast @@ -4,3 +4,45 @@ (component (export "" (instance)) ) + +(assert_invalid + (component (export "" (instance 0))) + "index out of bounds") + +(assert_invalid + (component (export "" (component 0))) + "index out of bounds") + +(assert_invalid + (component (export "" (module 0))) + "index out of bounds") + +(assert_invalid + (component (export "" (func 0))) + "index out of bounds") + +(assert_invalid + (component (export "" (value 0))) + "index out of bounds") + +(component + (import "1" (instance $i)) + (import "2" (module $m)) + (import "3" (component $c)) + (import "4" (value $v string)) + (import "5" (func $f)) + + (export "1" (instance $i)) + (export "2" (module $m)) + (export "3" (component $c)) + (export "4" (value $v)) + (export "5" (func $f)) +) + +(assert_invalid + (component + (import "" (value $v string)) + (export "1" (value $v)) + (export "2" (value $v)) + ) + "cannot be used more than once") diff --git a/tests/local/component-model/import.wast b/tests/local/component-model/import.wast index f6730354f9..090c8ce3bb 100644 --- a/tests/local/component-model/import.wast +++ b/tests/local/component-model/import.wast @@ -60,3 +60,37 @@ ) ) "duplicate import name `:a`") + +(assert_malformed + (component quote + "(import \"\" (func))" + "(import \"\" (func))" + ) + "duplicate import name `` already defined") + +(assert_malformed + (component quote + "(type (component" + "(import \"\" (func))" + "(import \"\" (func))" + "))" + ) + "duplicate import name `` already defined") + +(assert_invalid + (component + (import "" (func (type 100))) + ) + "type index out of bounds") + +(assert_invalid + (component + (module $m (func (export ""))) + (instance $i (instantiate (module $m))) + (func (canon.lift (type 100) (func $i ""))) + ) + "type index out of bounds") + +(component + (import "" (value string)) +) diff --git a/tests/local/component-model/instantiate.wast b/tests/local/component-model/instantiate.wast index fbd39b85be..4c5dbb709c 100644 --- a/tests/local/component-model/instantiate.wast +++ b/tests/local/component-model/instantiate.wast @@ -359,3 +359,223 @@ (instance (instantiate (module $final) (with "" (instance $b)))) ) + +(assert_invalid + (component (instance $i (export "" (func 0)))) + "function index out of bounds") + +(assert_invalid + (component (instance $i (export "" (instance 0)))) + "index out of bounds") + +(assert_invalid + (component (instance $i (export "" (component 0)))) + "index out of bounds") + +(assert_invalid + (component (instance $i (export "" (instance 0)))) + "index out of bounds") + +(assert_invalid + (component (instance $i (export "" (module 0)))) + "index out of bounds") + +(assert_invalid + (component (instance $i (export "" (value 0)))) + "index out of bounds") + +(assert_invalid + (component (instance core (export "" (func 0)))) + "index out of bounds") + +(assert_invalid + (component (instance core (export "" (table 0)))) + "index out of bounds") + +(assert_invalid + (component (instance core (export "" (global 0)))) + "index out of bounds") + +(assert_invalid + (component (instance core (export "" (memory 0)))) + "index out of bounds") + +(assert_invalid + (component + (import "" (instance $i)) + (module $m) + (instance (instantiate (module $m) (with "" (instance $i)))) + ) + "not a module instance") + +;; FIXME(#605) I think this should be invalid +(component + (module $m) + (instance $i (instantiate (module $m))) + (instance (instantiate (module $m) + (with "" (instance $i)) + (with "" (instance $i)) + )) +) + +(assert_invalid + (component + (module $m (func (export ""))) + (instance $i (instantiate (module $m))) + (instance (instantiate (module $m) + (with "" (instance $i)) + (with "" (instance $i)) + )) + ) + "duplicate instantiation argument name") + +(assert_invalid + (component + (module $m1 (func (export ""))) + (module $m2 (import "" "" (global i32))) + (instance $i (instantiate (module $m1))) + (instance (instantiate (module $m2) + (with "" (instance $i)) + )) + ) + "expected module instantiation argument `::` to be of type `global`") + +(assert_invalid + (component + (module $m) + (instance $i (instantiate (module $m))) + (component $c) + (instance (instantiate (component $c) (with "" (instance $i)))) + ) + "not a component instance") + +(assert_invalid + (component + (component $m) + (instance $i (instantiate (component $m))) + (instance (instantiate (component $m) + (with "" (instance $i)) + (with "" (instance $i)) + )) + ) + "name `` already defined") + +(assert_invalid + (component + (component $c (import "" (func))) + (instance (instantiate (component $c) + (with "" (component $c)) + )) + ) + "expected component instantiation argument `` to be of type `function`") + +(assert_invalid + (component + (component $c) + (instance (instantiate (component $c) + (with "" (module 0)) + )) + ) + "index out of bounds") + +(assert_invalid + (component + (component $c) + (instance (instantiate (component $c) + (with "" (value 0)) + )) + ) + "index out of bounds") + +(assert_invalid + (component + (component $c) + (instance (instantiate (component $c) + (with "" (instance 0)) + )) + ) + "index out of bounds") + +(assert_invalid + (component + (component $c) + (instance (instantiate (component $c) + (with "" (func 0)) + )) + ) + "index out of bounds") + +(assert_invalid + (component + (component $c) + (instance (instantiate (component $c) + (with "" (component 100)) + )) + ) + "index out of bounds") + +(assert_invalid + (component + (component $c) + (instance + (export "" (component $c)) + (export "" (component $c)) + ) + ) + "export name `` already defined") + +(component + (import "1" (instance $i)) + (import "2" (func $f)) + (import "3" (component $c)) + (import "4" (module $m)) + (import "5" (value $v string)) + (instance + (export "1" (instance $i)) + (export "2" (func $f)) + (export "3" (component $c)) + (export "4" (module $m)) + (export "5" (value $v)) + ) +) + +(component + (module $m + (func (export "1")) + (memory (export "2") 1) + (table (export "3") 1 funcref) + (global (export "4") i32 i32.const 0) + ) + (instance $i (instantiate (module $m))) + (instance core + (export "a" (func $i "1")) + (export "b" (memory $i "2")) + (export "c" (table $i "3")) + (export "d" (global $i "4")) + ) +) + +(assert_invalid + (component + (module $m (func (export ""))) + (instance $i (instantiate (module $m))) + (instance core + (export "" (func $i "")) + (export "" (func $i "")) + ) + ) + "export name `` already defined") + +(assert_invalid + (component + (component $c) + (instance $i (instantiate (component $c))) + (export "" (instance $i "")) + ) + "no export named ``") + +(assert_invalid + (component + (export "" (instance 100 "")) + ) + "index out of bounds") diff --git a/tests/local/component-model/intertypes.wast b/tests/local/component-model/intertypes.wast index 74fdf90a05..82de5f98a7 100644 --- a/tests/local/component-model/intertypes.wast +++ b/tests/local/component-model/intertypes.wast @@ -51,3 +51,69 @@ (type $A22c (expected unit $A8)) (type $A22d (expected $A9 $A10)) ) + +(assert_invalid + (component + (type $t (module)) + (type (func (param $t))) + ) + "not an interface type") + +(assert_invalid + (component + (type $t (module)) + (type (func (result $t))) + ) + "not an interface type") + +(assert_invalid + (component + (type $t (module)) + (type (value $t)) + ) + "not an interface type") + +(assert_invalid + (component + (type $t (module)) + (type (option $t)) + ) + "not an interface type") + +(assert_invalid + (component (type (option 0))) + "index out of bounds") +(assert_invalid + (component (type (list 0))) + "index out of bounds") +(assert_invalid + (component (type (record (field "x" 0)))) + "index out of bounds") +(assert_invalid + (component (type (variant (case "x" 0)))) + "index out of bounds") +(assert_invalid + (component (type (union 0))) + "index out of bounds") +(assert_invalid + (component (type (expected 0 1))) + "index out of bounds") +(assert_invalid + (component (type (tuple 0))) + "index out of bounds") + +(assert_invalid + (component (type (record (field "" s32)))) + "name cannot be empty") + +(assert_invalid + (component (type (variant (case "" s32)))) + "name cannot be empty") + +(assert_invalid + (component (type (flags ""))) + "name cannot be empty") + +(assert_invalid + (component (type (enum ""))) + "name cannot be empty") diff --git a/tests/local/component-model/invalid.wast b/tests/local/component-model/invalid.wast index 23c0f0adfc..8aac06bfab 100644 --- a/tests/local/component-model/invalid.wast +++ b/tests/local/component-model/invalid.wast @@ -17,25 +17,19 @@ "invalid leading byte") (assert_malformed - (module quote - "(component" - "(export \"\" (func $foo))" - ")" + (component quote + "(export \"\" (func $foo))" ) "failed to find func named") (assert_malformed - (module quote - "(component" - "(alias outer 100 $foo (func $foo))" - ")" + (component quote + "(alias outer 100 $foo (func $foo))" ) "component depth of `100` is too large") (assert_malformed - (module quote - "(component" - "(alias outer $nonexistent $foo (func $foo))" - ")" + (component quote + "(alias outer $nonexistent $foo (func $foo))" ) "outer component `nonexistent` not found") diff --git a/tests/local/component-model/start.wast b/tests/local/component-model/start.wast new file mode 100644 index 0000000000..b6f0d6b3bd --- /dev/null +++ b/tests/local/component-model/start.wast @@ -0,0 +1,55 @@ + +(assert_invalid + (component + (import "" (func $f (param string))) + (start $f (result)) + ) + "start function requires 1 arguments") + +(assert_invalid + (component + (import "" (func $f (param string))) + (import "v" (value $v string)) + (start $f (value $v) (value $v) (result)) + ) + "start function requires 1 arguments") + +(assert_invalid + (component + (import "" (func $f (param string) (param string))) + (import "v" (value $v string)) + (start $f (value $v) (value $v) (result)) + ) + "cannot be used more than once") + +(assert_invalid + (component + (import "" (func $f (param string) (param string))) + (import "v" (value $v string)) + (import "v2" (value $v2 u32)) + (start $f (value $v) (value $v2) (result)) + ) + "type mismatch for component start function argument 1") + +(component + (import "" (func $f (param string) (param string))) + (import "v" (value $v string)) + (import "v2" (value $v2 string)) + (start $f (value $v) (value $v2) (result)) +) + +(assert_invalid + (component + (import "" (func $f)) + (start $f (result)) + (start $f (result)) + ) + "cannot have more than one start") + +(assert_invalid + (component + (module $m (func (export ""))) + (instance $i (instantiate (module $m))) + (start (func $i "") (result)) + ) + "not a component function") diff --git a/tests/local/component-model/types.wast b/tests/local/component-model/types.wast index cdf5fdb15d..32617141de 100644 --- a/tests/local/component-model/types.wast +++ b/tests/local/component-model/types.wast @@ -52,8 +52,166 @@ (export "" (module 0)) ) "module index out of bounds") + (assert_invalid (component (export "" (instance 0)) ) "instance index out of bounds") + +(assert_invalid + (component + (type (module + (export "" (func (type 0))) + )) + ) + "type index out of bounds") + +(assert_invalid + (component + (type (module + (export "" (func)) + (export "" (func)) + )) + ) + "export name `` already defined") + +(assert_invalid + (component + (type (module + (import "" "" (func)) + (import "" "" (func)) + )) + ) + "duplicate import name") + +(assert_invalid + (component + (type (module + (import "" "" (memory 70000)) + )) + ) + "memory size must be at most") + +(assert_invalid + (component + (type (component + (export "" (func (type 0))) + )) + ) + "type index out of bounds") + +(assert_invalid + (component + (type (component + (export "" (func)) + (export "" (func)) + )) + ) + "export name `` already defined") + +(assert_invalid + (component + (type (component + (import "" (func)) + (import "" (func)) + )) + ) + "duplicate import name") + +(assert_invalid + (component $c + (type $t (component + (alias outer $c $t (type)) + )) + ) + "failed to find type named `$t`") + +(assert_invalid + (component $c + (type $t (component + (alias outer $c 0 (type)) + )) + ) + "type index out of bounds") + +(assert_invalid + (component $c + (type $f (func)) + (type $t (component + (alias outer 100 0 (type)) + )) + ) + "invalid outer alias count of 100") + +(assert_invalid + (component $c + (type $f (func)) + (type $t (component + (type (module + (export "" (func)) + (export "" (func)) + )) + )) + ) + "name `` already defined") + +(assert_invalid + (component + (type (instance + (export "" (func (type 0))) + )) + ) + "type index out of bounds") + +(assert_invalid + (component + (type (instance + (export "" (func)) + (export "" (func)) + )) + ) + "export name `` already defined") + +(assert_invalid + (component $c + (type $t (instance + (alias outer $c $t (type)) + )) + ) + "failed to find type named `$t`") + +(assert_invalid + (component $c + (type $t (instance + (alias outer $c 0 (type)) + )) + ) + "type index out of bounds") + +(assert_invalid + (component $c + (type $f (func)) + (type $t (instance + (alias outer 100 0 (type)) + )) + ) + "invalid outer alias count of 100") + +(assert_invalid + (component $c + (type $f (func)) + (type $t (instance + (type (module + (export "" (func)) + (export "" (func)) + )) + )) + ) + "name `` already defined") + +(assert_invalid + (component $c + (type $f (func (param "" string))) + ) + "function parameter name cannot be empty") diff --git a/tests/local/component-model/very-nested.wast b/tests/local/component-model/very-nested.wast index 4e94b71a1d..62f7b3ebea 100644 --- a/tests/local/component-model/very-nested.wast +++ b/tests/local/component-model/very-nested.wast @@ -1684,3 +1684,169 @@ (instance (instantiate (component $b) (with "" (component $a)))) ) "effective type size exceeds the limit") + +(assert_invalid + (component + (component $m0) + (component $m1 + (instance (export "0") (instantiate (component $m0))) + (instance (export "1") (instantiate (component $m0))) + (instance (export "2") (instantiate (component $m0))) + (instance (export "3") (instantiate (component $m0))) + (instance (export "4") (instantiate (component $m0))) + (instance (export "5") (instantiate (component $m0))) + (instance (export "6") (instantiate (component $m0))) + (instance (export "7") (instantiate (component $m0))) + (instance (export "8") (instantiate (component $m0))) + (instance (export "9") (instantiate (component $m0))) + ) + (component $m2 + (instance (export "0") (instantiate (component $m1))) + (instance (export "1") (instantiate (component $m1))) + (instance (export "2") (instantiate (component $m1))) + (instance (export "3") (instantiate (component $m1))) + (instance (export "4") (instantiate (component $m1))) + (instance (export "5") (instantiate (component $m1))) + (instance (export "6") (instantiate (component $m1))) + (instance (export "7") (instantiate (component $m1))) + (instance (export "8") (instantiate (component $m1))) + (instance (export "9") (instantiate (component $m1))) + ) + (component $m3 + (instance (export "0") (instantiate (component $m2))) + (instance (export "1") (instantiate (component $m2))) + (instance (export "2") (instantiate (component $m2))) + (instance (export "3") (instantiate (component $m2))) + (instance (export "4") (instantiate (component $m2))) + (instance (export "5") (instantiate (component $m2))) + (instance (export "6") (instantiate (component $m2))) + (instance (export "7") (instantiate (component $m2))) + (instance (export "8") (instantiate (component $m2))) + (instance (export "9") (instantiate (component $m2))) + ) + (component $m4 + (instance (export "0") (instantiate (component $m3))) + (instance (export "1") (instantiate (component $m3))) + (instance (export "2") (instantiate (component $m3))) + (instance (export "3") (instantiate (component $m3))) + (instance (export "4") (instantiate (component $m3))) + (instance (export "5") (instantiate (component $m3))) + (instance (export "6") (instantiate (component $m3))) + (instance (export "7") (instantiate (component $m3))) + (instance (export "8") (instantiate (component $m3))) + (instance (export "9") (instantiate (component $m3))) + ) + (component $m5 + (instance (export "0") (instantiate (component $m4))) + (instance (export "1") (instantiate (component $m4))) + (instance (export "2") (instantiate (component $m4))) + (instance (export "3") (instantiate (component $m4))) + (instance (export "4") (instantiate (component $m4))) + (instance (export "5") (instantiate (component $m4))) + (instance (export "6") (instantiate (component $m4))) + (instance (export "7") (instantiate (component $m4))) + (instance (export "8") (instantiate (component $m4))) + (instance (export "9") (instantiate (component $m4))) + ) + (component $m6 + (instance (export "0") (instantiate (component $m5))) + (instance (export "1") (instantiate (component $m5))) + (instance (export "2") (instantiate (component $m5))) + (instance (export "3") (instantiate (component $m5))) + (instance (export "4") (instantiate (component $m5))) + (instance (export "5") (instantiate (component $m5))) + (instance (export "6") (instantiate (component $m5))) + (instance (export "7") (instantiate (component $m5))) + (instance (export "8") (instantiate (component $m5))) + (instance (export "9") (instantiate (component $m5))) + ) + (component $m7 + (instance (export "0") (instantiate (component $m6))) + (instance (export "1") (instantiate (component $m6))) + (instance (export "2") (instantiate (component $m6))) + (instance (export "3") (instantiate (component $m6))) + (instance (export "4") (instantiate (component $m6))) + (instance (export "5") (instantiate (component $m6))) + (instance (export "6") (instantiate (component $m6))) + (instance (export "7") (instantiate (component $m6))) + (instance (export "8") (instantiate (component $m6))) + (instance (export "9") (instantiate (component $m6))) + ) + ) + "effective type size exceeds the limit") + +(assert_invalid + (component + ;; size(t0) == 1 + (type $t0 (flags "x")) + + ;; size(t1) == 10 + (type $t1 (record + (field "0" $t0) + (field "1" $t0) + (field "2" $t0) + (field "3" $t0) + (field "4" $t0) + (field "5" $t0) + (field "6" $t0) + (field "7" $t0) + (field "8" $t0) + (field "9" $t0) + )) + + ;; size(t2) == 100 + (type $t2 (record + (field "0" $t1) + (field "1" $t1) + (field "2" $t1) + (field "3" $t1) + (field "4" $t1) + (field "5" $t1) + (field "6" $t1) + (field "7" $t1) + (field "8" $t1) + (field "9" $t1) + )) + + ;; size(t3) == 1000 + (type $t3 (record + (field "0" $t2) + (field "1" $t2) + (field "2" $t2) + (field "3" $t2) + (field "4" $t2) + (field "5" $t2) + (field "6" $t2) + (field "7" $t2) + (field "8" $t2) + (field "9" $t2) + )) + + ;; size(t4) == 10000 + (type $t4 (record + (field "0" $t3) + (field "1" $t3) + (field "2" $t3) + (field "3" $t3) + (field "4" $t3) + (field "5" $t3) + (field "6" $t3) + (field "7" $t3) + (field "8" $t3) + (field "9" $t3) + )) + + (type $f (func + (param $t4) + (param $t4) + (param $t4) + (param $t4) + (param $t4) + (param $t4) + (param $t4) + (param $t4) + (param $t4) + (param $t4) + )) + ) + "effective type size exceeds the limit") diff --git a/tests/roundtrip.rs b/tests/roundtrip.rs index f898cf2560..4d4d439a44 100644 --- a/tests/roundtrip.rs +++ b/tests/roundtrip.rs @@ -288,7 +288,7 @@ impl TestState { // offset is a text-parser error, whereas with memory64 // support that error is deferred until later. if !test.iter().any(|t| t == "memory64") { - if let QuoteWat::Quote(_, src) = module { + if let QuoteWat::QuoteModule(_, src) = module { if src .iter() .filter_map(|(_, s)| str::from_utf8(s).ok())