summaryrefslogtreecommitdiff
path: root/src/tools/fuzzing/fuzzing.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/fuzzing/fuzzing.cpp')
-rw-r--r--src/tools/fuzzing/fuzzing.cpp74
1 files changed, 71 insertions, 3 deletions
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index 54ff3533b..3fb8c1ea5 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -404,12 +404,16 @@ void TranslateToFuzzReader::setupGlobals() {
void TranslateToFuzzReader::setupTags() {
Index num = upTo(3);
for (size_t i = 0; i < num; i++) {
- auto tag = builder.makeTag(Names::getValidTagName(wasm, "tag$"),
- Signature(getControlFlowType(), Type::none));
- wasm.addTag(std::move(tag));
+ addTag();
}
}
+void TranslateToFuzzReader::addTag() {
+ auto tag = builder.makeTag(Names::getValidTagName(wasm, "tag$"),
+ Signature(getControlFlowType(), Type::none));
+ wasm.addTag(std::move(tag));
+}
+
void TranslateToFuzzReader::finalizeMemory() {
auto& memory = wasm.memories[0];
for (auto& segment : wasm.dataSegments) {
@@ -1123,6 +1127,7 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
WeightedOption{&Self::makeBreak, Important},
&Self::makeCall,
&Self::makeCallIndirect)
+ .add(FeatureSet::ExceptionHandling, &Self::makeTry)
.add(FeatureSet::GC | FeatureSet::ReferenceTypes, &Self::makeCallRef);
}
if (type.isSingle()) {
@@ -1232,6 +1237,7 @@ Expression* TranslateToFuzzReader::_makeunreachable() {
&Self::makeSwitch,
&Self::makeDrop,
&Self::makeReturn)
+ .add(FeatureSet::ExceptionHandling, &Self::makeThrow)
.add(FeatureSet::GC | FeatureSet::ReferenceTypes, &Self::makeCallRef);
return (this->*pick(options))(Type::unreachable);
}
@@ -1363,6 +1369,54 @@ Expression* TranslateToFuzzReader::makeIf(Type type) {
return ret;
}
+Expression* TranslateToFuzzReader::makeTry(Type type) {
+ auto* body = make(type);
+ std::vector<Name> catchTags;
+ std::vector<Expression*> catchBodies;
+ auto numTags = upTo(MAX_TRY_CATCHES);
+ std::unordered_set<Tag*> usedTags;
+ for (Index i = 0; i < numTags; i++) {
+ if (wasm.tags.empty()) {
+ addTag();
+ }
+ auto* tag = pick(wasm.tags).get();
+ if (usedTags.count(tag)) {
+ continue;
+ }
+ usedTags.insert(tag);
+ catchTags.push_back(tag->name);
+ }
+ // The number of tags in practice may be fewer than we planned.
+ numTags = catchTags.size();
+ auto numCatches = numTags;
+ if (numTags == 0 || oneIn(2)) {
+ // Add a catch-all.
+ numCatches++;
+ }
+ for (Index i = 0; i < numCatches; i++) {
+ // Catch bodies (aside from a catch-all) begin with a pop.
+ Expression* prefix = nullptr;
+ if (i < numTags) {
+ auto tagType = wasm.getTag(catchTags[i])->sig.params;
+ if (tagType != Type::none) {
+ auto* pop = builder.makePop(tagType);
+ // Capture the pop in a local, so that it can be used later.
+ // TODO: add a good chance for using this particular local in this catch
+ // TODO: reuse an existing var if there is one
+ auto index = builder.addVar(funcContext->func, tagType);
+ prefix = builder.makeLocalSet(index, pop);
+ }
+ }
+ auto* catchBody = make(type);
+ if (prefix) {
+ catchBody = builder.makeSequence(prefix, catchBody);
+ }
+ catchBodies.push_back(catchBody);
+ }
+ // TODO: delegate stuff
+ return builder.makeTry(body, catchTags, catchBodies);
+}
+
Expression* TranslateToFuzzReader::makeBreak(Type type) {
if (funcContext->breakableStack.empty()) {
return makeTrivial(type);
@@ -3499,6 +3553,20 @@ Expression* TranslateToFuzzReader::makeI31Get(Type type) {
return builder.makeI31Get(i31, bool(oneIn(2)));
}
+Expression* TranslateToFuzzReader::makeThrow(Type type) {
+ assert(type == Type::unreachable);
+ if (wasm.tags.empty()) {
+ addTag();
+ }
+ auto* tag = pick(wasm.tags).get();
+ auto tagType = tag->sig.params;
+ std::vector<Expression*> operands;
+ for (auto t : tagType) {
+ operands.push_back(make(t));
+ }
+ return builder.makeThrow(tag, operands);
+}
+
Expression* TranslateToFuzzReader::makeMemoryInit() {
if (!allowMemory) {
return makeTrivial(Type::none);