summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/wasm-validator.cpp22
-rw-r--r--test/lit/validation/closed-world-interface.wast11
2 files changed, 22 insertions, 11 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 179235fbc..cd90e767e 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -3734,13 +3734,23 @@ static void validateFeatures(Module& module, ValidationInfo& info) {
static void validateClosedWorldInterface(Module& module, ValidationInfo& info) {
// Error if there are any publicly exposed heap types beyond the types of
- // publicly exposed functions.
- std::unordered_set<HeapType> publicFuncTypes;
- ModuleUtils::iterImportedFunctions(
- module, [&](Function* func) { publicFuncTypes.insert(func->type); });
+ // publicly exposed functions. Note that we must include all types in the rec
+ // groups that are used, as if a type if public then all types in its rec
+ // group are as well.
+ std::unordered_set<RecGroup> publicRecGroups;
+ ModuleUtils::iterImportedFunctions(module, [&](Function* func) {
+ publicRecGroups.insert(func->type.getRecGroup());
+ });
for (auto& ex : module.exports) {
if (ex->kind == ExternalKind::Function) {
- publicFuncTypes.insert(module.getFunction(ex->value)->type);
+ publicRecGroups.insert(module.getFunction(ex->value)->type.getRecGroup());
+ }
+ }
+
+ std::unordered_set<HeapType> publicTypes;
+ for (auto& group : publicRecGroups) {
+ for (auto type : group) {
+ publicTypes.insert(type);
}
}
@@ -3749,7 +3759,7 @@ static void validateClosedWorldInterface(Module& module, ValidationInfo& info) {
auto ignorable = getIgnorablePublicTypes();
for (auto type : ModuleUtils::getPublicHeapTypes(module)) {
- if (!publicFuncTypes.count(type) && !ignorable.count(type)) {
+ if (!publicTypes.count(type) && !ignorable.count(type)) {
auto name = type.toString();
if (auto it = module.typeNames.find(type); it != module.typeNames.end()) {
name = it->second.name.toString();
diff --git a/test/lit/validation/closed-world-interface.wast b/test/lit/validation/closed-world-interface.wast
index 06cf1cef7..daedaf990 100644
--- a/test/lit/validation/closed-world-interface.wast
+++ b/test/lit/validation/closed-world-interface.wast
@@ -3,10 +3,6 @@
;; RUN: not wasm-opt -all --closed-world %s 2>&1 | filecheck %s
-;; This is pulled in because it is part of a rec group with $partial-pair-0.
-;; CHECK: publicly exposed type disallowed with a closed world: $partial-pair-1, on
-;; CHECK-NEXT: (func)
-
;; This is pulled in by a global.
;; CHECK: publicly exposed type disallowed with a closed world: $array, on
;; CHECK-NEXT: (array (mut i32))
@@ -32,8 +28,13 @@
(type $exported-pair-1 (func (param (ref $exported-pair-0))))
)
(rec
+ ;; This is on an exported function.
(type $partial-pair-0 (func))
+ ;; The latter type types are not public, but allowed to be because the
+ ;; entire rec group is allowed due to the first.
(type $partial-pair-1 (func))
+ ;; Test a non-function type.
+ (type $partial-pair-2 (struct))
)
(type $private (func (param v128)))
@@ -61,7 +62,7 @@
;; Ok even though it is an import instead of an export.
(func $5 (import "env" "test5") (type $exported-pair-1))
- ;; Not ok because another type in the group is not on the boundary.
+ ;; Ok, and we also allow the other type in the group.
(func $6 (export "test6") (type $partial-pair-0)
(unreachable)
)