diff options
Diffstat (limited to 'src/tools/fuzzing/fuzzing.cpp')
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 74 |
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); |