summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/fuzzing.h5
-rw-r--r--src/tools/fuzzing/fuzzing.cpp31
-rw-r--r--test/passes/fuzz_metrics_noprint.bin.txt53
-rw-r--r--test/passes/translate-to-fuzz_all-features_metrics_noprint.txt65
4 files changed, 82 insertions, 72 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index aff2a0aa3..bdadaba5a 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -193,9 +193,8 @@ private:
}
void recombine(Function* func);
void mutate(Function* func);
- // Fix up changes that may have broken validation - types are correct in our
- // modding, but not necessarily labels.
- void fixLabels(Function* func);
+ // Fix up the IR after recombination and mutation.
+ void fixAfterChanges(Function* func);
void modifyInitialFunctions();
// Initial wasm contents may have come from a test that uses the drop pattern:
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index d91266d49..af2a34078 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -544,7 +544,7 @@ Function* TranslateToFuzzReader::addFunction() {
// with more possible sets.
// Recombination, mutation, etc. can break validation; fix things up
// after.
- fixLabels(func);
+ fixAfterChanges(func);
}
// Add hang limit checks after all other operations on the function body.
wasm.addFunction(func);
@@ -690,7 +690,6 @@ void TranslateToFuzzReader::recombine(Function* func) {
Module& wasm;
Scanner& scanner;
TranslateToFuzzReader& parent;
- bool needRefinalize = false;
Modder(Module& wasm, Scanner& scanner, TranslateToFuzzReader& parent)
: wasm(wasm), scanner(scanner), parent(parent) {}
@@ -702,18 +701,11 @@ void TranslateToFuzzReader::recombine(Function* func) {
assert(!candidates.empty()); // this expression itself must be there
auto* rep = parent.pick(candidates);
replaceCurrent(ExpressionManipulator::copy(rep, wasm));
- if (rep->type != curr->type) {
- // Subtyping changes require us to finalize later.
- needRefinalize = true;
- }
}
}
};
Modder modder(wasm, scanner, *this);
modder.walk(func->body);
- if (modder.needRefinalize) {
- ReFinalize().walkFunctionInModule(func, &wasm);
- }
}
void TranslateToFuzzReader::mutate(Function* func) {
@@ -721,15 +713,28 @@ void TranslateToFuzzReader::mutate(Function* func) {
if (oneIn(2)) {
return;
}
+
struct Modder : public PostWalker<Modder, UnifiedExpressionVisitor<Modder>> {
Module& wasm;
TranslateToFuzzReader& parent;
+ // Whether to replace with unreachable. This can lead to less code getting
+ // executed, so we don't want to do it all the time even in a big function.
+ bool allowUnreachable;
+
Modder(Module& wasm, TranslateToFuzzReader& parent)
- : wasm(wasm), parent(parent) {}
+ : wasm(wasm), parent(parent) {
+ // Half the time, never replace with an unreachable. The other half, do it
+ // sometimes (but even so, only rarely, see below).
+ allowUnreachable = parent.oneIn(2);
+ }
void visitExpression(Expression* curr) {
if (parent.oneIn(10) && parent.canBeArbitrarilyReplaced(curr)) {
+ if (allowUnreachable && parent.oneIn(10)) {
+ replaceCurrent(parent.make(Type::unreachable));
+ return;
+ }
// For constants, perform only a small tweaking in some cases.
if (auto* c = curr->dynCast<Const>()) {
if (parent.oneIn(2)) {
@@ -749,7 +754,7 @@ void TranslateToFuzzReader::mutate(Function* func) {
modder.walk(func->body);
}
-void TranslateToFuzzReader::fixLabels(Function* func) {
+void TranslateToFuzzReader::fixAfterChanges(Function* func) {
struct Fixer
: public ControlFlowWalker<Fixer, UnifiedExpressionVisitor<Fixer>> {
Module& wasm;
@@ -818,6 +823,8 @@ void TranslateToFuzzReader::fixLabels(Function* func) {
};
Fixer fixer(wasm, *this);
fixer.walk(func->body);
+
+ // Refinalize at the end, after labels are all fixed up.
ReFinalize().walkFunctionInModule(func, &wasm);
}
@@ -855,7 +862,7 @@ void TranslateToFuzzReader::modifyInitialFunctions() {
// check variations on initial testcases even at the risk of OOB.
recombine(func);
mutate(func);
- fixLabels(func);
+ fixAfterChanges(func);
}
}
// Remove a start function - the fuzzing harness expects code to run only
diff --git a/test/passes/fuzz_metrics_noprint.bin.txt b/test/passes/fuzz_metrics_noprint.bin.txt
index cf94c2f3d..b7d64cee2 100644
--- a/test/passes/fuzz_metrics_noprint.bin.txt
+++ b/test/passes/fuzz_metrics_noprint.bin.txt
@@ -1,33 +1,34 @@
total
- [exports] : 15
- [funcs] : 21
+ [exports] : 41
+ [funcs] : 52
[globals] : 7
[imports] : 4
[memories] : 1
[memory-data] : 4
- [table-data] : 7
+ [table-data] : 21
[tables] : 1
[tags] : 0
- [total] : 2012
- [vars] : 60
- Binary : 195
- Block : 269
- Break : 80
- Call : 67
- CallIndirect : 14
- Const : 373
- Drop : 12
- GlobalGet : 164
- GlobalSet : 65
- If : 110
- Load : 47
- LocalGet : 176
- LocalSet : 116
- Loop : 39
- Nop : 24
- RefFunc : 7
- Return : 74
- Select : 18
- Store : 26
- Unary : 135
- Unreachable : 1
+ [total] : 8251
+ [vars] : 153
+ Binary : 661
+ Block : 1232
+ Break : 320
+ Call : 303
+ CallIndirect : 86
+ Const : 1458
+ Drop : 57
+ GlobalGet : 646
+ GlobalSet : 295
+ If : 479
+ Load : 157
+ LocalGet : 617
+ LocalSet : 473
+ Loop : 208
+ Nop : 137
+ RefFunc : 21
+ Return : 338
+ Select : 58
+ Store : 91
+ Switch : 1
+ Unary : 611
+ Unreachable : 2
diff --git a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
index 97d1b637d..3f725452b 100644
--- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
+++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
@@ -1,6 +1,6 @@
total
- [exports] : 10
- [funcs] : 14
+ [exports] : 15
+ [funcs] : 18
[globals] : 6
[imports] : 5
[memories] : 1
@@ -8,35 +8,38 @@ total
[table-data] : 6
[tables] : 1
[tags] : 0
- [total] : 610
- [vars] : 52
- ArrayInit : 5
- AtomicFence : 4
- AtomicRMW : 2
- Binary : 66
- Block : 78
- Break : 9
- Call : 21
+ [total] : 541
+ [vars] : 31
+ ArrayInit : 7
+ AtomicFence : 1
+ AtomicNotify : 1
+ Binary : 68
+ Block : 64
+ Break : 3
+ Call : 14
+ CallIndirect : 1
CallRef : 1
- Const : 146
+ Const : 119
+ DataDrop : 1
Drop : 9
- GlobalGet : 46
- GlobalSet : 22
- I31New : 3
- If : 28
- Load : 13
- LocalGet : 20
- LocalSet : 17
- Loop : 8
- Nop : 16
- RefFunc : 8
- RefIsNull : 2
- RefNull : 5
- Return : 28
- SIMDExtract : 1
- Select : 1
- Store : 4
- StructNew : 6
+ GlobalGet : 49
+ GlobalSet : 23
+ I31Get : 1
+ I31New : 4
+ If : 24
+ Load : 16
+ LocalGet : 26
+ LocalSet : 18
+ Loop : 5
+ MemoryCopy : 1
+ Nop : 6
+ RefFunc : 7
+ RefIsNull : 3
+ RefNull : 3
+ Return : 26
+ SIMDTernary : 1
+ Select : 2
+ Store : 2
TupleExtract : 1
- TupleMake : 7
- Unary : 33
+ TupleMake : 5
+ Unary : 29