summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2023-06-21 10:28:43 -0700
committerGitHub <noreply@github.com>2023-06-21 10:28:43 -0700
commit7aeaf136fbb8b59c32250a563f1e2ef548c56032 (patch)
treefef070c37a61c88cdef815cf3bd5c59e8b26962c /src
parentb783932cd3c27b3a5fc1cde300a0a78bb05e15bc (diff)
downloadbinaryen-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.h4
-rw-r--r--src/tools/fuzzing/fuzzing.cpp74
-rw-r--r--src/tools/fuzzing/parameters.h4
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;