Skip to content

Commit 8958df4

Browse files
authored
Validate descriptor declarations (#7392)
To ensure soundness, there are very particular rules about how described and descriptor type declarations must relate to one another and their supertypes. Implement and test these rules.
1 parent 7508e81 commit 8958df4

File tree

3 files changed

+231
-0
lines changed

3 files changed

+231
-0
lines changed

src/wasm-type.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,20 @@ struct TypeBuilder {
816816
InvalidFuncType,
817817
// A non-shared field of a shared heap type.
818818
InvalidUnsharedField,
819+
// A describes clause on a non-struct type.
820+
NonStructDescribes,
821+
// The described type is an invalid forward reference.
822+
ForwardDescribesReference,
823+
// The described type does not have this type as a descriptor.
824+
MismatchedDescribes,
825+
// A descriptor clause on a non-struct type.
826+
NonStructDescriptor,
827+
// The descriptor type does not describe this type.
828+
MismatchedDescriptor,
829+
// A non-shared descriptor on a shared type.
830+
InvalidUnsharedDescriptor,
831+
// A non-shared type described by a shared type.
832+
InvalidUnsharedDescribes,
819833
};
820834

821835
struct Error {

src/wasm/wasm-type.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,20 @@ std::ostream& operator<<(std::ostream& os, TypeBuilder::ErrorReason reason) {
14641464
return os << "Continuation has invalid function type";
14651465
case TypeBuilder::ErrorReason::InvalidUnsharedField:
14661466
return os << "Heap type has an invalid unshared field";
1467+
case TypeBuilder::ErrorReason::NonStructDescribes:
1468+
return os << "Describes clause on a non-struct type";
1469+
case TypeBuilder::ErrorReason::ForwardDescribesReference:
1470+
return os << "Describes clause is a forward reference";
1471+
case TypeBuilder::ErrorReason::MismatchedDescribes:
1472+
return os << "Described type is not a matching descriptor";
1473+
case TypeBuilder::ErrorReason::NonStructDescriptor:
1474+
return os << "Descriptor clause on a non-struct type";
1475+
case TypeBuilder::ErrorReason::MismatchedDescriptor:
1476+
return os << "Descriptor type does not describe heap type";
1477+
case TypeBuilder::ErrorReason::InvalidUnsharedDescriptor:
1478+
return os << "Heap type has an invalid unshared descriptor";
1479+
case TypeBuilder::ErrorReason::InvalidUnsharedDescribes:
1480+
return os << "Heap type describes an invalid unshared type";
14671481
}
14681482
WASM_UNREACHABLE("Unexpected error reason");
14691483
}
@@ -2370,6 +2384,25 @@ bool isValidSupertype(const HeapTypeInfo& sub, const HeapTypeInfo& super) {
23702384
if (sub.kind != super.kind) {
23712385
return false;
23722386
}
2387+
if (sub.descriptor) {
2388+
// A supertype of a type with a (descriptor $x) must either not have a
2389+
// descriptor or have a (descriptor $y) where $y is the declared supertype
2390+
// of $x.
2391+
if (super.descriptor && sub.descriptor->supertype != super.descriptor) {
2392+
return false;
2393+
}
2394+
} else {
2395+
// A supertype of a type without a descriptor must also not have a
2396+
// descriptor.
2397+
if (super.descriptor) {
2398+
return false;
2399+
}
2400+
}
2401+
// A supertype of a type must have a describes clause iff the type has a
2402+
// describes clause.
2403+
if (bool(sub.described) != bool(super.described)) {
2404+
return false;
2405+
}
23732406
SubTyper typer;
23742407
switch (sub.kind) {
23752408
case HeapTypeKind::Func:
@@ -2399,12 +2432,38 @@ validateType(HeapTypeInfo& info, std::unordered_set<HeapType>& seenTypes) {
23992432
return TypeBuilder::ErrorReason::InvalidSupertype;
24002433
}
24012434
}
2435+
if (auto* desc = info.described) {
2436+
if (info.kind != HeapTypeKind::Struct) {
2437+
return TypeBuilder::ErrorReason::NonStructDescribes;
2438+
}
2439+
assert(desc->isTemp && "unexpected canonical described type");
2440+
if (!seenTypes.count(HeapType(uintptr_t(desc)))) {
2441+
return TypeBuilder::ErrorReason::ForwardDescribesReference;
2442+
}
2443+
if (desc->descriptor != &info) {
2444+
return TypeBuilder::ErrorReason::MismatchedDescribes;
2445+
}
2446+
}
2447+
if (auto* desc = info.descriptor) {
2448+
if (info.kind != HeapTypeKind::Struct) {
2449+
return TypeBuilder::ErrorReason::NonStructDescriptor;
2450+
}
2451+
if (desc->described != &info) {
2452+
return TypeBuilder::ErrorReason::MismatchedDescriptor;
2453+
}
2454+
}
24022455
if (info.isContinuation()) {
24032456
if (!info.continuation.type.isSignature()) {
24042457
return TypeBuilder::ErrorReason::InvalidFuncType;
24052458
}
24062459
}
24072460
if (info.share == Shared) {
2461+
if (info.described && info.described->share != Shared) {
2462+
return TypeBuilder::ErrorReason::InvalidUnsharedDescribes;
2463+
}
2464+
if (info.descriptor && info.descriptor->share != Shared) {
2465+
return TypeBuilder::ErrorReason::InvalidUnsharedDescriptor;
2466+
}
24082467
switch (info.kind) {
24092468
case HeapTypeKind::Func:
24102469
// TODO: Figure out and enforce shared function rules.

test/spec/descriptors.wast

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
(module
2+
(rec
3+
(type (descriptor 1 (struct)))
4+
(type (describes 0 (struct)))
5+
)
6+
)
7+
8+
(assert_invalid
9+
(module
10+
(rec
11+
(type (descriptor 1 (struct)))
12+
(type (struct))
13+
)
14+
)
15+
"descriptor with no matching describes"
16+
)
17+
18+
19+
(assert_invalid
20+
(module
21+
(rec
22+
(type (struct))
23+
(type (describes 0 (struct)))
24+
)
25+
)
26+
"describes with no matching descriptor"
27+
)
28+
29+
(assert_invalid
30+
(module
31+
(rec
32+
(type (describes 1 (struct)))
33+
(type (descriptor 0 (struct)))
34+
)
35+
)
36+
"forward describes reference"
37+
)
38+
39+
(assert_invalid
40+
(module
41+
(rec
42+
(type (descriptor 1 (array i8)))
43+
(type (describes 0 (struct)))
44+
)
45+
)
46+
"descriptor clause on non-struct type"
47+
)
48+
49+
(assert_invalid
50+
(module
51+
(rec
52+
(type (descriptor 1 (struct)))
53+
(type (describes 0 (array i8)))
54+
)
55+
)
56+
"describes clause on non-struct type"
57+
)
58+
59+
(module
60+
(rec
61+
(type (shared (descriptor 1 (struct))))
62+
(type (shared (describes 0 (struct))))
63+
)
64+
)
65+
66+
(assert_invalid
67+
(module
68+
(rec
69+
(type (shared (descriptor 1 (struct))))
70+
(type (describes 0 (struct)))
71+
)
72+
)
73+
"unshared descriptor type"
74+
)
75+
76+
;; TODO: allow this?
77+
(assert_invalid
78+
(module
79+
(rec
80+
(type (descriptor 1 (struct)))
81+
(type (shared (describes 0 (struct))))
82+
)
83+
)
84+
"unshared described types"
85+
)
86+
87+
(module
88+
(rec
89+
(type $super (sub (descriptor $super-desc (struct))))
90+
(type $super-desc (sub (describes $super (struct))))
91+
)
92+
(rec
93+
(type $sub (sub $super (descriptor $sub-desc (struct))))
94+
(type $sub-desc (sub $super-desc (describes $sub (struct))))
95+
)
96+
)
97+
98+
(module
99+
(type $super (sub (struct)))
100+
(rec
101+
(type $other (sub (descriptor $super-desc (struct))))
102+
(type $super-desc (sub (describes $other (struct))))
103+
)
104+
(rec
105+
(type $sub (sub $super (descriptor $sub-desc (struct))))
106+
(type $sub-desc (sub $super-desc (describes $sub (struct))))
107+
)
108+
)
109+
110+
(assert_invalid
111+
(module
112+
(type $super (sub (struct)))
113+
(type $super-desc (sub (struct)))
114+
(rec
115+
(type $sub (sub $super (descriptor $sub-desc (struct))))
116+
(type $sub-desc (sub $super-desc (describes $sub (struct))))
117+
)
118+
)
119+
"supertype of descriptor must be a descriptor"
120+
)
121+
122+
(assert_invalid
123+
(module
124+
(rec
125+
(type $other (sub (descriptor $super-desc (struct))))
126+
(type $super-desc (sub (describes $other (struct))))
127+
(type $super (sub (descriptor $other-desc (struct))))
128+
(type $other-desc (sub (describes $super (struct))))
129+
)
130+
(rec
131+
(type $sub (sub $super (descriptor $sub-desc (struct))))
132+
(type $sub-desc (sub $super-desc (describes $sub (struct))))
133+
)
134+
)
135+
"supertype of described type must be described by supertype of descriptor"
136+
)
137+
138+
(assert_invalid
139+
(module
140+
(rec
141+
(type $super (sub (descriptor $super-desc (struct))))
142+
(type $super-desc (sub (describes $super (struct))))
143+
)
144+
(type $sub (sub $super (struct)))
145+
)
146+
"supertype of type without descriptor cannot have descriptor"
147+
)
148+
149+
(assert_invalid
150+
(module
151+
(rec
152+
(type $super (sub (descriptor $super-desc (struct))))
153+
(type $super-desc (sub (describes $super (struct))))
154+
)
155+
(type $sub (sub $super-desc (struct)))
156+
)
157+
"supertype of non-descriptor type cannot be a descriptor"
158+
)

0 commit comments

Comments
 (0)