Skip to content

Commit 19dd23d

Browse files
authored
[EH] Fuzz exnref in tables (#7289)
* Add an exnref table. * Add table operations (also for funcref, while we are at it). * Add exnref to getConcrete(), so there is a chance to emit table.get.
1 parent 2bee4bb commit 19dd23d

3 files changed

Lines changed: 139 additions & 41 deletions

File tree

src/tools/fuzzing.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ class TranslateToFuzzReader {
161161
Name HANG_LIMIT_GLOBAL;
162162

163163
Name funcrefTableName;
164+
Name exnrefTableName;
164165

165166
std::unordered_map<Type, Name> logImportNames;
166167
Name throwImportName;
@@ -465,6 +466,8 @@ class TranslateToFuzzReader {
465466
Expression* makeSIMDShift();
466467
Expression* makeSIMDLoad();
467468
Expression* makeBulkMemory(Type type);
469+
Expression* makeTableGet(Type type);
470+
Expression* makeTableSet(Type type);
468471
// TODO: support other RefIs variants, and rename this
469472
Expression* makeRefIsNull(Type type);
470473
Expression* makeRefEq(Type type);

src/tools/fuzzing/fuzzing.cpp

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,22 @@ void TranslateToFuzzReader::setupTables() {
546546
segment->setName(Names::getValidElementSegmentName(wasm, "elem$"), false);
547547
wasm.addElementSegment(std::move(segment));
548548
}
549+
550+
// When EH is enabled, set up an exnref table.
551+
if (wasm.features.hasExceptionHandling()) {
552+
Type exnref = Type(HeapType::exn, Nullable);
553+
Address initial = upTo(10);
554+
Address max = oneIn(2) ? initial + upTo(4) : Memory::kUnlimitedSize;
555+
auto tablePtr =
556+
builder.makeTable(Names::getValidTableName(wasm, "exnref_table"),
557+
exnref,
558+
initial,
559+
max,
560+
Type::i32); // TODO: wasm64
561+
tablePtr->hasExplicitName = true;
562+
table = wasm.addTable(std::move(tablePtr));
563+
exnrefTableName = table->name;
564+
}
549565
}
550566

551567
void TranslateToFuzzReader::setupGlobals() {
@@ -1953,6 +1969,14 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
19531969
if (heapType.isBasic()) {
19541970
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
19551971
&Self::makeBasicRef);
1972+
if (type.isNullable() && funcContext) {
1973+
if (heapType == HeapType::func) {
1974+
options.add(FeatureSet::ReferenceTypes, &Self::makeTableGet);
1975+
}
1976+
if (heapType == HeapType::exn) {
1977+
options.add(FeatureSet::ExceptionHandling, &Self::makeTableGet);
1978+
}
1979+
}
19561980
} else {
19571981
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
19581982
&Self::makeCompoundRef);
@@ -2000,6 +2024,7 @@ Expression* TranslateToFuzzReader::_makenone() {
20002024
&Self::makeGlobalSet)
20012025
.add(FeatureSet::BulkMemory, &Self::makeBulkMemory)
20022026
.add(FeatureSet::Atomics, &Self::makeAtomic)
2027+
.add(FeatureSet::ReferenceTypes, &Self::makeTableSet)
20032028
.add(FeatureSet::ExceptionHandling, &Self::makeTry)
20042029
.add(FeatureSet::ExceptionHandling, &Self::makeTryTable)
20052030
.add(FeatureSet::ExceptionHandling, &Self::makeImportThrowing)
@@ -4418,6 +4443,58 @@ Expression* TranslateToFuzzReader::makeBulkMemory(Type type) {
44184443
WASM_UNREACHABLE("invalid value");
44194444
}
44204445

4446+
Expression* TranslateToFuzzReader::makeTableGet(Type type) {
4447+
// Emit a get from the funcref table (which always exists) or the exnref one
4448+
// (which might not, if EH is disabled).
4449+
auto makeTableGet = [&](Name tableName) {
4450+
auto* table = wasm.getTable(tableName);
4451+
// Usually emit in-bounds gets, to avoid trapping, but rarely allow
4452+
// anything.
4453+
Expression* index;
4454+
if (allowOOB && oneIn(10)) {
4455+
index = make(table->addressType);
4456+
} else {
4457+
index = builder.makeConst(
4458+
Literal::makeFromInt32(upTo(table->initial), table->addressType));
4459+
}
4460+
return builder.makeTableGet(tableName, index, table->type);
4461+
};
4462+
if (type.getHeapType() == HeapType::exn) {
4463+
return makeTableGet(exnrefTableName);
4464+
} else if (type.getHeapType() == HeapType::func) {
4465+
return makeTableGet(funcrefTableName);
4466+
} else {
4467+
WASM_UNREACHABLE("bad TableGet type");
4468+
}
4469+
}
4470+
4471+
Expression* TranslateToFuzzReader::makeTableSet(Type type) {
4472+
assert(type == Type::none);
4473+
4474+
// Emit a set to either the funcref table (which always exists) or the exnref
4475+
// one (which might not, if EH is disabled).
4476+
auto makeTableSet = [&](Name tableName) {
4477+
auto* table = wasm.getTable(tableName);
4478+
// Usually emit in-bounds sets, to avoid trapping, but rarely allow
4479+
// anything.
4480+
Expression* index;
4481+
if (allowOOB && oneIn(10)) {
4482+
index = make(table->addressType);
4483+
} else {
4484+
index = builder.makeConst(
4485+
Literal::makeFromInt32(upTo(table->initial), table->addressType));
4486+
}
4487+
auto* value = make(table->type);
4488+
return builder.makeTableSet(tableName, index, value);
4489+
};
4490+
if (exnrefTableName && oneIn(2)) {
4491+
return makeTableSet(exnrefTableName);
4492+
} else {
4493+
assert(funcrefTableName);
4494+
return makeTableSet(funcrefTableName);
4495+
}
4496+
}
4497+
44214498
Expression* TranslateToFuzzReader::makeRefIsNull(Type type) {
44224499
assert(type == Type::i32);
44234500
assert(wasm.features.hasReferenceTypes());
@@ -4922,8 +4999,8 @@ Type TranslateToFuzzReader::getSingleConcreteType() {
49224999
auto nullability = getNullability();
49235000
return Type(heapType, nullability);
49245001
}
4925-
// Skip (ref func), (ref extern), and (ref i31) for now
4926-
// because there is no way to create them in globals. TODO.
5002+
// Skip (ref func|extern|i31|exn) because there is no way to create them in
5003+
// globals. TODO
49275004
using WeightedOption = FeatureOptions<Type>::WeightedOption;
49285005
return pick(FeatureOptions<Type>()
49295006
.add(FeatureSet::MVP,
@@ -4935,6 +5012,9 @@ Type TranslateToFuzzReader::getSingleConcreteType() {
49355012
.add(FeatureSet::ReferenceTypes,
49365013
Type(HeapType::func, Nullable),
49375014
Type(HeapType::ext, Nullable))
5015+
.add(FeatureSet::ExceptionHandling,
5016+
// Type(HeapType::exn, NonNullable),
5017+
Type(HeapType::exn, Nullable))
49385018
.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
49395019
// Type(HeapType::func, NonNullable),
49405020
// Type(HeapType::ext, NonNullable),
Lines changed: 54 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,61 @@
11
Metrics
22
total
3-
[exports] : 13
4-
[funcs] : 14
5-
[globals] : 4
6-
[imports] : 12
3+
[exports] : 9
4+
[funcs] : 8
5+
[globals] : 1
6+
[imports] : 11
77
[memories] : 1
88
[memory-data] : 112
9-
[table-data] : 2
10-
[tables] : 1
9+
[table-data] : 0
10+
[tables] : 2
1111
[tags] : 0
12-
[total] : 654
13-
[vars] : 15
14-
ArrayGet : 1
15-
ArrayLen : 1
16-
ArrayNew : 6
17-
ArrayNewFixed : 11
18-
Binary : 74
19-
Block : 64
20-
Call : 43
21-
CallIndirect : 1
22-
Const : 170
23-
Drop : 7
24-
GlobalGet : 38
25-
GlobalSet : 32
26-
If : 18
27-
Load : 17
28-
LocalGet : 42
29-
LocalSet : 23
30-
Loop : 3
31-
Nop : 3
32-
RefAs : 2
33-
RefFunc : 7
12+
[total] : 738
13+
[vars] : 40
14+
ArrayCopy : 1
15+
ArrayFill : 1
16+
ArrayLen : 3
17+
ArrayNew : 5
18+
ArrayNewFixed : 1
19+
AtomicFence : 2
20+
AtomicNotify : 2
21+
AtomicRMW : 1
22+
Binary : 82
23+
Block : 80
24+
BrOn : 4
25+
Break : 13
26+
Call : 29
27+
CallRef : 1
28+
Const : 134
29+
Drop : 15
30+
GlobalGet : 26
31+
GlobalSet : 26
32+
I31Get : 3
33+
If : 26
34+
Load : 16
35+
LocalGet : 85
36+
LocalSet : 51
37+
Loop : 6
38+
MemoryFill : 2
39+
Nop : 5
40+
Pop : 4
41+
RefAs : 10
42+
RefEq : 1
43+
RefFunc : 2
44+
RefI31 : 12
45+
RefIsNull : 1
3446
RefNull : 7
35-
Return : 3
36-
Select : 1
47+
RefTest : 2
48+
Return : 4
49+
SIMDExtract : 7
50+
Select : 7
3751
Store : 1
38-
StringConst : 1
39-
StringEncode : 1
40-
StructNew : 37
41-
StructSet : 1
42-
Throw : 1
43-
TryTable : 2
44-
TupleMake : 3
45-
Unary : 17
46-
Unreachable : 16
52+
StringConst : 3
53+
StringEncode : 2
54+
StringMeasure : 1
55+
StructGet : 2
56+
StructNew : 2
57+
StructSet : 2
58+
Try : 6
59+
TryTable : 5
60+
Unary : 24
61+
Unreachable : 13

0 commit comments

Comments
 (0)