From 755cb78fa0a1445c7a14290b97d26db270159aa6 Mon Sep 17 00:00:00 2001 From: Yuri Iozzelli Date: Wed, 8 Nov 2023 15:08:28 +0100 Subject: [PATCH] [interpreter] add new assertions for custom sections (#19) * [interpreter] add new assertions for custom sections assert_malformed and assert_invalid now have a _custom variant, for asserting custom section/annotation errors. The js implementation is a no-op, since no JS engine currently support any kind of diagnostic for custom sections. * Update interpreter/script/run.ml Co-authored-by: Andreas Rossberg * Update interpreter/script/run.ml Co-authored-by: Andreas Rossberg * revert check_module change * add custom assertions in the test harness --------- Co-authored-by: Andreas Rossberg --- interpreter/script/js.ml | 12 ++++++++++++ interpreter/script/run.ml | 19 +++++++++++++++++-- interpreter/script/script.ml | 2 ++ interpreter/text/arrange.ml | 8 ++++++++ interpreter/text/lexer.mll | 2 ++ interpreter/text/parser.mly | 5 +++++ test/custom/custom/custom_annot.wast | 28 ++++++++++++++-------------- test/custom/name/name_annot.wast | 6 +++--- test/harness/async_index.js | 6 ++++++ test/harness/sync_index.js | 12 ++++++++++++ 10 files changed, 81 insertions(+), 19 deletions(-) diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml index 1ae30f55b..4db73ab5c 100644 --- a/interpreter/script/js.ml +++ b/interpreter/script/js.ml @@ -107,6 +107,10 @@ function assert_malformed(bytes) { throw new Error("Wasm decoding failure expected"); } +function assert_malformed_custom(bytes) { + return; +} + function assert_invalid(bytes) { try { module(bytes, false) } catch (e) { if (e instanceof WebAssembly.CompileError) return; @@ -114,6 +118,10 @@ function assert_invalid(bytes) { throw new Error("Wasm validation failure expected"); } +function assert_invalid_custom(bytes) { + return; +} + function assert_unlinkable(bytes) { let mod = module(bytes); try { new WebAssembly.Instance(mod, registry) } catch (e) { @@ -571,8 +579,12 @@ let of_assertion mods ass = match ass.it with | AssertMalformed (def, _) -> "assert_malformed(" ^ of_definition def ^ ");" + | AssertMalformedCustom (def, _) -> + "assert_malformed_custom(" ^ of_definition def ^ ");" | AssertInvalid (def, _) -> "assert_invalid(" ^ of_definition def ^ ");" + | AssertInvalidCustom (def, _) -> + "assert_invalid_custom(" ^ of_definition def ^ ");" | AssertUnlinkable (def, _) -> "assert_unlinkable(" ^ of_definition def ^ ");" | AssertUninstantiable (def, _) -> diff --git a/interpreter/script/run.ml b/interpreter/script/run.ml index 90d2aa75c..e2b3e7076 100644 --- a/interpreter/script/run.ml +++ b/interpreter/script/run.ml @@ -450,9 +450,15 @@ let run_assertion ass = (match ignore (run_definition def) with | exception Decode.Code (_, msg) -> assert_message ass.at "decoding" msg re | exception Parse.Syntax (_, msg) -> assert_message ass.at "parsing" msg re + | _ -> Assert.error ass.at "expected decoding/parsing error" + ) + + | AssertMalformedCustom (def, re) -> + trace "Asserting malformed custom..."; + (match ignore (run_definition def) with | exception Custom.Syntax (_, msg) -> assert_message ass.at "annotation parsing" msg re - | _ -> Assert.error ass.at "expected decoding/parsing error" + | _ -> Assert.error ass.at "expected custom decoding/parsing error" ) | AssertInvalid (def, re) -> @@ -463,9 +469,18 @@ let run_assertion ass = with | exception Valid.Invalid (_, msg) -> assert_message ass.at "validation" msg re + | _ -> Assert.error ass.at "expected validation error" + ) + + | AssertInvalidCustom (def, re) -> + trace "Asserting invalid custom..."; + (match + let m, cs = run_definition def in + Valid.check_module_with_custom (m, cs) + with | exception Custom.Invalid (_, msg) -> assert_message ass.at "custom validation" msg re - | _ -> Assert.error ass.at "expected validation error" + | _ -> Assert.error ass.at "expected custom validation error" ) | AssertUnlinkable (def, re) -> diff --git a/interpreter/script/script.ml b/interpreter/script/script.ml index e7ad2fa90..cc089f5a5 100644 --- a/interpreter/script/script.ml +++ b/interpreter/script/script.ml @@ -40,7 +40,9 @@ and result' = type assertion = assertion' Source.phrase and assertion' = | AssertMalformed of definition * string + | AssertMalformedCustom of definition * string | AssertInvalid of definition * string + | AssertInvalidCustom of definition * string | AssertUnlinkable of definition * string | AssertUninstantiable of definition * string | AssertReturn of action * result list diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index 458e130a6..67fd55d1a 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -758,8 +758,16 @@ let assertion mode ass = | _ -> [Node ("assert_malformed", [definition `Original None def; Atom (string re)])] ) + | AssertMalformedCustom (def, re) -> + (match mode, def.it with + | `Binary, Quoted _ -> [] + | _ -> + [Node ("assert_malformed_custom", [definition `Original None def; Atom (string re)])] + ) | AssertInvalid (def, re) -> [Node ("assert_invalid", [definition mode None def; Atom (string re)])] + | AssertInvalidCustom (def, re) -> + [Node ("assert_invalid_custom", [definition mode None def; Atom (string re)])] | AssertUnlinkable (def, re) -> [Node ("assert_unlinkable", [definition mode None def; Atom (string re)])] | AssertUninstantiable (def, re) -> diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index 012387a6a..1ea00e522 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -680,6 +680,8 @@ rule token = parse | "get" -> GET | "assert_malformed" -> ASSERT_MALFORMED | "assert_invalid" -> ASSERT_INVALID + | "assert_malformed_custom" -> ASSERT_MALFORMED_CUSTOM + | "assert_invalid_custom" -> ASSERT_INVALID_CUSTOM | "assert_unlinkable" -> ASSERT_UNLINKABLE | "assert_return" -> ASSERT_RETURN | "assert_trap" -> ASSERT_TRAP diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index b940ad0d9..dc9501fcd 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -258,6 +258,7 @@ let parse_annots (m : module_) : Custom.section list = %token MODULE BIN QUOTE %token SCRIPT REGISTER INVOKE GET %token ASSERT_MALFORMED ASSERT_INVALID ASSERT_UNLINKABLE +%token ASSERT_MALFORMED_CUSTOM ASSERT_INVALID_CUSTOM %token ASSERT_RETURN ASSERT_TRAP ASSERT_EXHAUSTION %token NAN %token INPUT OUTPUT @@ -1062,6 +1063,10 @@ assertion : { AssertMalformed (snd $3, $4) @@ at () } | LPAR ASSERT_INVALID script_module STRING RPAR { AssertInvalid (snd $3, $4) @@ at () } + | LPAR ASSERT_MALFORMED_CUSTOM script_module STRING RPAR + { AssertMalformedCustom (snd $3, $4) @@ at () } + | LPAR ASSERT_INVALID_CUSTOM script_module STRING RPAR + { AssertInvalidCustom (snd $3, $4) @@ at () } | LPAR ASSERT_UNLINKABLE script_module STRING RPAR { AssertUnlinkable (snd $3, $4) @@ at () } | LPAR ASSERT_TRAP script_module STRING RPAR diff --git a/test/custom/custom/custom_annot.wast b/test/custom/custom/custom_annot.wast index 6d6735e85..19ed6bd77 100644 --- a/test/custom/custom/custom_annot.wast +++ b/test/custom/custom/custom_annot.wast @@ -22,22 +22,22 @@ ;; Malformed name -(assert_malformed +(assert_malformed_custom (module quote "(@custom)") "@custom annotation: missing section name" ) -(assert_malformed +(assert_malformed_custom (module quote "(@custom 4)") "@custom annotation: missing section name" ) -(assert_malformed +(assert_malformed_custom (module quote "(@custom bla)") "@custom annotation: missing section name" ) -(assert_malformed +(assert_malformed_custom (module quote "(@custom \"\\df\")") "@custom annotation: malformed UTF-8 encoding" ) @@ -45,32 +45,32 @@ ;; Malformed placement -(assert_malformed +(assert_malformed_custom (module quote "(@custom \"bla\" here)") "@custom annotation: unexpected token" ) -(assert_malformed +(assert_malformed_custom (module quote "(@custom \"bla\" after)") "@custom annotation: unexpected token" ) -(assert_malformed +(assert_malformed_custom (module quote "(@custom \"bla\" (after))") "@custom annotation: malformed section kind" ) -(assert_malformed +(assert_malformed_custom (module quote "(@custom \"bla\" (type))") "@custom annotation: malformed placement" ) -(assert_malformed +(assert_malformed_custom (module quote "(@custom \"bla\" (aft type))") "@custom annotation: malformed placement" ) -(assert_malformed +(assert_malformed_custom (module quote "(@custom \"bla\" (before types))") "@custom annotation: malformed section kind" ) @@ -78,22 +78,22 @@ ;; Misplaced -(assert_malformed +(assert_malformed_custom (module quote "(type (@custom \"bla\") $t (func))") "misplaced @custom annotation" ) -(assert_malformed +(assert_malformed_custom (module quote "(func (@custom \"bla\"))") "misplaced @custom annotation" ) -(assert_malformed +(assert_malformed_custom (module quote "(func (block (@custom \"bla\")))") "misplaced @custom annotation" ) -(assert_malformed +(assert_malformed_custom (module quote "(func (nop (@custom \"bla\")))") "misplaced @custom annotation" ) diff --git a/test/custom/name/name_annot.wast b/test/custom/name/name_annot.wast index 5421151fd..7a0e30c00 100644 --- a/test/custom/name/name_annot.wast +++ b/test/custom/name/name_annot.wast @@ -4,17 +4,17 @@ (module $moduel (@name "Modül")) -(assert_malformed +(assert_malformed_custom (module quote "(module (@name \"M1\") (@name \"M2\"))") "@name annotation: multiple module" ) -(assert_malformed +(assert_malformed_custom (module quote "(module (func) (@name \"M\"))") "misplaced @name annotation" ) -(assert_malformed +(assert_malformed_custom (module quote "(module (start $f (@name \"M\")) (func $f))") "misplaced @name annotation" ) diff --git a/test/harness/async_index.js b/test/harness/async_index.js index bb7d4cf5d..6a1ff3cfb 100644 --- a/test/harness/async_index.js +++ b/test/harness/async_index.js @@ -176,6 +176,12 @@ function assert_invalid(bytes) { const assert_malformed = assert_invalid; +function assert_invalid_custom(bytes) { + module(bytes); +} + +const assert_malformed_custom = assert_invalid_custom; + function instance(bytes, imports, valid = true) { const test = valid ? "Test that WebAssembly instantiation succeeds" diff --git a/test/harness/sync_index.js b/test/harness/sync_index.js index 79469ee9b..0bb9ef68c 100644 --- a/test/harness/sync_index.js +++ b/test/harness/sync_index.js @@ -191,6 +191,18 @@ function assert_invalid(bytes) { const assert_malformed = assert_invalid; +function assert_invalid_custom(bytes) { + uniqueTest(() => { + try { + module(bytes, /* valid */ true); + } catch(e) { + throw new Error('failed on custom section error'); + } + }, "A wast module that should have an invalid or malformed custom section."); +} + +const assert_malformed_custom = assert_invalid_custom; + function instance(bytes, imports = registry, valid = true) { if (imports instanceof Result) { if (imports.isError())