diff options
author | Alon Zakai <azakai@google.com> | 2023-06-21 10:28:43 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-21 10:28:43 -0700 |
commit | 7aeaf136fbb8b59c32250a563f1e2ef548c56032 (patch) | |
tree | fef070c37a61c88cdef815cf3bd5c59e8b26962c /src | |
parent | b783932cd3c27b3a5fc1cde300a0a78bb05e15bc (diff) | |
download | binaryen-7aeaf136fbb8b59c32250a563f1e2ef548c56032.tar.gz binaryen-7aeaf136fbb8b59c32250a563f1e2ef548c56032.tar.bz2 binaryen-7aeaf136fbb8b59c32250a563f1e2ef548c56032.zip |
Fuzzing for Try and Throw (#5776)
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/fuzzing.h | 4 | ||||
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 74 | ||||
-rw-r--r-- | src/tools/fuzzing/parameters.h | 4 |
3 files changed, 79 insertions, 3 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 5a9ebdf22..e29a6ddaf 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -207,6 +207,7 @@ private: void setupTables(); void setupGlobals(); void setupTags(); + void addTag(); void finalizeMemory(); void finalizeTable(); void prepareHangLimitSupport(); @@ -283,6 +284,7 @@ private: Expression* makeMaybeBlock(Type type); Expression* buildIf(const struct ThreeArgs& args, Type type); Expression* makeIf(Type type); + Expression* makeTry(Type type); Expression* makeBreak(Type type); Expression* makeCall(Type type); Expression* makeCallIndirect(Type type); @@ -358,6 +360,8 @@ private: // get/set). Expression* makeArrayBulkMemoryOp(Type type); Expression* makeI31Get(Type type); + Expression* makeThrow(Type type); + Expression* makeMemoryInit(); Expression* makeDataDrop(); Expression* makeMemoryCopy(); 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); diff --git a/src/tools/fuzzing/parameters.h b/src/tools/fuzzing/parameters.h index dd5c8d82c..51531681b 100644 --- a/src/tools/fuzzing/parameters.h +++ b/src/tools/fuzzing/parameters.h @@ -67,6 +67,10 @@ constexpr int HANG_LIMIT = 100; // the maximum amount of new GC types (structs, etc.) to create constexpr int MAX_NEW_GC_TYPES = 25; +// the maximum amount of catches in each try (not including a catch-all, if +// present). +constexpr int MAX_TRY_CATCHES = 4; + // constexpr size_t VeryImportant = 4; constexpr size_t Important = 2; |