Skip to content

Commit ec9feee

Browse files
kripkenradekdoulik
authored andcommitted
Allow rec groups of public function types in closed world (WebAssembly#6053)
Closed-world mode allows function types to escape if they are on exported functions, because that has been possible since wasm MVP and cannot be avoided. But we need to also allow all types in those type's rec groups as well. Consider this case: (module (rec (type $0 (func)) (type $1 (func)) ) (func "0" (type $0) (nop) ) (func "1" (type $1) (nop) ) ) The two exported functions make the two types public, so this module validates in closed world mode. Now imagine that metadce removes one export: (module (rec (type $0 (func)) (type $1 (func)) ) (func "0" (type $0) (nop) ) ;; The export "1" is gone. ) Before this PR that no longer validates, because it only marks the type $0 as public. But when a type is public that makes its entire rec group public, so $1 is errored on. To fix that, this PR allows all types in a rec group of an exported function's type, which makes that last module validate.
1 parent 8d0c015 commit ec9feee

File tree

2 files changed

+22
-11
lines changed

2 files changed

+22
-11
lines changed

src/wasm/wasm-validator.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3734,13 +3734,23 @@ static void validateFeatures(Module& module, ValidationInfo& info) {
37343734

37353735
static void validateClosedWorldInterface(Module& module, ValidationInfo& info) {
37363736
// Error if there are any publicly exposed heap types beyond the types of
3737-
// publicly exposed functions.
3738-
std::unordered_set<HeapType> publicFuncTypes;
3739-
ModuleUtils::iterImportedFunctions(
3740-
module, [&](Function* func) { publicFuncTypes.insert(func->type); });
3737+
// publicly exposed functions. Note that we must include all types in the rec
3738+
// groups that are used, as if a type if public then all types in its rec
3739+
// group are as well.
3740+
std::unordered_set<RecGroup> publicRecGroups;
3741+
ModuleUtils::iterImportedFunctions(module, [&](Function* func) {
3742+
publicRecGroups.insert(func->type.getRecGroup());
3743+
});
37413744
for (auto& ex : module.exports) {
37423745
if (ex->kind == ExternalKind::Function) {
3743-
publicFuncTypes.insert(module.getFunction(ex->value)->type);
3746+
publicRecGroups.insert(module.getFunction(ex->value)->type.getRecGroup());
3747+
}
3748+
}
3749+
3750+
std::unordered_set<HeapType> publicTypes;
3751+
for (auto& group : publicRecGroups) {
3752+
for (auto type : group) {
3753+
publicTypes.insert(type);
37443754
}
37453755
}
37463756

@@ -3749,7 +3759,7 @@ static void validateClosedWorldInterface(Module& module, ValidationInfo& info) {
37493759
auto ignorable = getIgnorablePublicTypes();
37503760

37513761
for (auto type : ModuleUtils::getPublicHeapTypes(module)) {
3752-
if (!publicFuncTypes.count(type) && !ignorable.count(type)) {
3762+
if (!publicTypes.count(type) && !ignorable.count(type)) {
37533763
auto name = type.toString();
37543764
if (auto it = module.typeNames.find(type); it != module.typeNames.end()) {
37553765
name = it->second.name.toString();

test/lit/validation/closed-world-interface.wast

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
;; RUN: not wasm-opt -all --closed-world %s 2>&1 | filecheck %s
44

55

6-
;; This is pulled in because it is part of a rec group with $partial-pair-0.
7-
;; CHECK: publicly exposed type disallowed with a closed world: $partial-pair-1, on
8-
;; CHECK-NEXT: (func)
9-
106
;; This is pulled in by a global.
117
;; CHECK: publicly exposed type disallowed with a closed world: $array, on
128
;; CHECK-NEXT: (array (mut i32))
@@ -32,8 +28,13 @@
3228
(type $exported-pair-1 (func (param (ref $exported-pair-0))))
3329
)
3430
(rec
31+
;; This is on an exported function.
3532
(type $partial-pair-0 (func))
33+
;; The latter type types are not public, but allowed to be because the
34+
;; entire rec group is allowed due to the first.
3635
(type $partial-pair-1 (func))
36+
;; Test a non-function type.
37+
(type $partial-pair-2 (struct))
3738
)
3839

3940
(type $private (func (param v128)))
@@ -61,7 +62,7 @@
6162
;; Ok even though it is an import instead of an export.
6263
(func $5 (import "env" "test5") (type $exported-pair-1))
6364

64-
;; Not ok because another type in the group is not on the boundary.
65+
;; Ok, and we also allow the other type in the group.
6566
(func $6 (export "test6") (type $partial-pair-0)
6667
(unreachable)
6768
)

0 commit comments

Comments
 (0)