| /* | |
| * Copyright 2023 WebAssembly Community Group participants | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include <set> | |
| #include <string> | |
| #include <vector> | |
| #include "shared-constants.h" | |
| #include "support/string.h" | |
| #include "wasm-binary.h" | |
| #include "wasm-builder.h" | |
| #include "wasm-features.h" | |
| #include "wasm-validator.h" | |
| #include "gtest/gtest.h" | |
| using namespace wasm; | |
| // Check that the validator does not crash on missing tags in catch statements | |
| // (invalid parse, so cannot be reproduced with Python test suite) | |
| TEST(ValidatorTest, MissingCatchTag) { | |
| WasmValidator validator; | |
| Module module; | |
| module.features.enable(FeatureSet::ExceptionHandling); | |
| auto tryExp = module.allocator.alloc<Try>(); | |
| tryExp->name = "tst1"; | |
| auto bodyExp = module.allocator.alloc<Const>(); | |
| bodyExp->value = Literal(1); | |
| tryExp->body = bodyExp; | |
| tryExp->catchTags.push_back(wasm::Name("foo")); | |
| auto catchBodyExp = module.allocator.alloc<Const>(); | |
| catchBodyExp->value = Literal(2); | |
| tryExp->catchBodies.push_back(catchBodyExp); | |
| Function function = Function(); | |
| function.body = tryExp; | |
| WasmValidator::Flags flags = | |
| WasmValidator::FlagValues::Globally | WasmValidator::FlagValues::Quiet; | |
| EXPECT_FALSE(validator.validate(&function, module, flags)); | |
| } | |
| TEST(ValidatorTest, ReturnUnreachable) { | |
| Module module; | |
| Builder builder(module); | |
| // (return (unreachable)) should be invalid if a function has no return type. | |
| auto func = | |
| builder.makeFunction("func", | |
| {}, | |
| Signature(Type::none, Type::none), | |
| {}, | |
| builder.makeReturn(builder.makeUnreachable())); | |
| auto flags = | |
| WasmValidator::FlagValues::Globally | WasmValidator::FlagValues::Quiet; | |
| EXPECT_FALSE(WasmValidator{}.validate(func.get(), module, flags)); | |
| } | |
| TEST(ValidatorTest, UnreachableCastDescEq) { | |
| // The parser will error trying to parse a ref.cast_desc_eq with a | |
| // non-matching descriptor type, so we must construct the IR directly to test | |
| // the validator. | |
| Module module; | |
| module.features = FeatureSet::All; | |
| Builder builder(module); | |
| auto func = builder.makeFunction( | |
| "func", | |
| {}, | |
| Signature(Type::none, Type::none), | |
| {}, | |
| builder.makeDrop(builder.makeRefCast(builder.makeUnreachable(), | |
| builder.makeStructNew(Struct{}, {}), | |
| Type::unreachable))); | |
| ASSERT_EQ(func->body->type, Type(Type::unreachable)); | |
| auto flags = | |
| WasmValidator::FlagValues::Globally | WasmValidator::FlagValues::Quiet; | |
| EXPECT_FALSE(WasmValidator{}.validate(func.get(), module, flags)); | |
| } | |
| TEST(ValidatorTest, ContNewUnreachable) { | |
| Module module; | |
| module.features = FeatureSet::All; | |
| Builder builder(module); | |
| auto sig = Signature(Type::none, Type::none); | |
| module.addFunction(builder.makeFunction( | |
| "f", {}, Signature(Type::none, Type::none), {}, builder.makeUnreachable())); | |
| auto contType = HeapType(Continuation(sig)); | |
| auto contRefType = Type(contType, NonNullable); | |
| // Create a cont.new with a concrete type despite an unreachable child. This | |
| // is not valid, but we should not crash while validating it. | |
| auto* contNew = builder.makeContNew(contType, builder.makeUnreachable()); | |
| contNew->type = contRefType; | |
| auto testFunc = builder.makeFunction( | |
| "test", {}, Signature(Type::none, contRefType), {}, contNew); | |
| auto flags = | |
| WasmValidator::FlagValues::Globally | WasmValidator::FlagValues::Quiet; | |
| EXPECT_FALSE(WasmValidator{}.validate(testFunc.get(), module, flags)); | |
| } |