Skip to content

Commit 7261008

Browse files
authored
Fast pass fuzzing (#1258)
* add fuzz-pass option, which picks random passes to fuzz in each wasm-opt invocation
1 parent 5e4ea07 commit 7261008

2 files changed

Lines changed: 85 additions & 24 deletions

File tree

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ struct BinaryArgs {
5454

5555
class TranslateToFuzzReader {
5656
public:
57-
TranslateToFuzzReader(Module& wasm) : wasm(wasm), builder(wasm) {}
58-
59-
void read(std::string& filename) {
57+
TranslateToFuzzReader(Module& wasm, std::string& filename) : wasm(wasm), builder(wasm) {
6058
auto input(read_file<std::vector<char>>(filename, Flags::Binary, Flags::Release));
6159
bytes.swap(input);
6260
pos = 0;
@@ -65,7 +63,80 @@ class TranslateToFuzzReader {
6563
if (bytes.size() == 0) {
6664
bytes.push_back(0);
6765
}
68-
build();
66+
}
67+
68+
void pickPasses(OptimizationOptions& options) {
69+
while (options.passes.size() < 20 && !finishedInput && !oneIn(3)) {
70+
switch (upTo(32)) {
71+
case 0:
72+
case 1:
73+
case 2:
74+
case 3:
75+
case 4: {
76+
options.passes.push_back("O");
77+
options.passOptions.optimizeLevel = upTo(4);
78+
options.passOptions.shrinkLevel = upTo(4);
79+
break;
80+
}
81+
case 5: options.passes.push_back("coalesce-locals"); break;
82+
case 6: options.passes.push_back("code-pushing"); break;
83+
case 7: options.passes.push_back("code-folding"); break;
84+
case 8: options.passes.push_back("dce"); break;
85+
case 9: options.passes.push_back("duplicate-function-elimination"); break;
86+
case 10: options.passes.push_back("flatten"); break;
87+
case 11: options.passes.push_back("inlining"); break;
88+
case 12: options.passes.push_back("inlining-optimizing"); break;
89+
case 13: options.passes.push_back("local-cse"); break;
90+
case 14: options.passes.push_back("memory-packing"); break;
91+
case 15: options.passes.push_back("merge-blocks"); break;
92+
case 16: options.passes.push_back("optimize-instructions"); break;
93+
case 17: options.passes.push_back("pick-load-signs"); break;
94+
case 18: options.passes.push_back("precompute"); break;
95+
case 19: options.passes.push_back("precompute-propagate"); break;
96+
case 20: options.passes.push_back("remove-unused-brs"); break;
97+
case 21: options.passes.push_back("remove-unused-module-elements"); break;
98+
case 22: options.passes.push_back("remove-unused-names"); break;
99+
case 23: options.passes.push_back("reorder-functions"); break;
100+
case 24: options.passes.push_back("reorder-locals"); break;
101+
case 25: {
102+
options.passes.push_back("flatten");
103+
options.passes.push_back("rereloop");
104+
break;
105+
}
106+
case 26: options.passes.push_back("simplify-locals"); break;
107+
case 27: options.passes.push_back("simplify-locals-notee"); break;
108+
case 28: options.passes.push_back("simplify-locals-nostructure"); break;
109+
case 29: options.passes.push_back("simplify-locals-notee-nostructure"); break;
110+
case 30: options.passes.push_back("ssa"); break;
111+
case 31: options.passes.push_back("vacuum"); break;
112+
default: WASM_UNREACHABLE();
113+
}
114+
}
115+
if (oneIn(2)) {
116+
options.passOptions.optimizeLevel = upTo(4);
117+
}
118+
if (oneIn(2)) {
119+
options.passOptions.shrinkLevel = upTo(4);
120+
}
121+
std::cout << "opt level: " << options.passOptions.optimizeLevel << '\n';
122+
std::cout << "shrink level: " << options.passOptions.shrinkLevel << '\n';
123+
}
124+
125+
void build() {
126+
setupMemory();
127+
setupTable();
128+
setupGlobals();
129+
// keep adding functions until we run out of input
130+
while (!finishedInput) {
131+
addFunction();
132+
}
133+
if (HANG_LIMIT > 0) {
134+
addHangLimitSupport();
135+
}
136+
if (DE_NAN) {
137+
addDeNanSupport();
138+
}
139+
finalizeTable();
69140
}
70141

71142
private:
@@ -141,23 +212,6 @@ class TranslateToFuzzReader {
141212
return Literal(get64()).reinterpretf64();
142213
}
143214

144-
void build() {
145-
setupMemory();
146-
setupTable();
147-
setupGlobals();
148-
// keep adding functions until we run out of input
149-
while (!finishedInput) {
150-
addFunction();
151-
}
152-
if (HANG_LIMIT > 0) {
153-
addHangLimitSupport();
154-
}
155-
if (DE_NAN) {
156-
addDeNanSupport();
157-
}
158-
finalizeTable();
159-
}
160-
161215
void setupMemory() {
162216
wasm.memory.exists = true;
163217
// use one page

src/tools/wasm-opt.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include "shell-interface.h"
3434
#include "optimization-options.h"
3535
#include "execution-results.h"
36-
#include "translate-to-fuzz.h"
36+
#include "fuzzing.h"
3737
#include "js-wrapper.h"
3838
#include "spec-wrapper.h"
3939

@@ -68,6 +68,7 @@ int main(int argc, const char* argv[]) {
6868
bool fuzzBinary = false;
6969
std::string extraFuzzCommand;
7070
bool translateToFuzz = false;
71+
bool fuzzPasses = false;
7172
std::string emitJSWrapper;
7273
std::string emitSpecWrapper;
7374

@@ -97,6 +98,9 @@ int main(int argc, const char* argv[]) {
9798
.add("--translate-to-fuzz", "-ttf", "Translate the input into a valid wasm module *somehow*, useful for fuzzing",
9899
Options::Arguments::Zero,
99100
[&](Options *o, const std::string &arguments) { translateToFuzz = true; })
101+
.add("--fuzz-passes", "-fp", "Pick a random set of passes to run, useful for fuzzing. this depends on translate-to-fuzz (it picks the passes from the input)",
102+
Options::Arguments::Zero,
103+
[&](Options *o, const std::string &arguments) { fuzzPasses = true; })
100104
.add("--emit-js-wrapper", "-ejw", "Emit a JavaScript wrapper file that can run the wasm with some test values, useful for fuzzing",
101105
Options::Arguments::One,
102106
[&](Options *o, const std::string &arguments) { emitJSWrapper = arguments; })
@@ -134,8 +138,11 @@ int main(int argc, const char* argv[]) {
134138
}
135139
} else {
136140
// translate-to-fuzz
137-
TranslateToFuzzReader reader(wasm);
138-
reader.read(options.extra["infile"]);
141+
TranslateToFuzzReader reader(wasm, options.extra["infile"]);
142+
if (fuzzPasses) {
143+
reader.pickPasses(options);
144+
}
145+
reader.build();
139146
if (!WasmValidator().validate(wasm, features)) {
140147
WasmPrinter::printModule(&wasm);
141148
std::cerr << "translate-to-fuzz must always generate a valid module";

0 commit comments

Comments
 (0)