From a16992b92461e57b7b8c7ef81aa120038641c74b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 30 Oct 2017 12:48:38 -0700 Subject: [PATCH 1/2] add fuzz-pass option, which picks random passes to fuzz in each wasm-opt invocation --- src/tools/{translate-to-fuzz.h => fuzzing.h} | 96 +++++++++++++++----- src/tools/wasm-opt.cpp | 13 ++- 2 files changed, 85 insertions(+), 24 deletions(-) rename src/tools/{translate-to-fuzz.h => fuzzing.h} (93%) diff --git a/src/tools/translate-to-fuzz.h b/src/tools/fuzzing.h similarity index 93% rename from src/tools/translate-to-fuzz.h rename to src/tools/fuzzing.h index b9aaea397ee..cddd5a3ec07 100644 --- a/src/tools/translate-to-fuzz.h +++ b/src/tools/fuzzing.h @@ -54,9 +54,7 @@ struct BinaryArgs { class TranslateToFuzzReader { public: - TranslateToFuzzReader(Module& wasm) : wasm(wasm), builder(wasm) {} - - void read(std::string& filename) { + TranslateToFuzzReader(Module& wasm, std::string& filename) : wasm(wasm), builder(wasm) { auto input(read_file>(filename, Flags::Binary, Flags::Release)); bytes.swap(input); pos = 0; @@ -65,7 +63,80 @@ class TranslateToFuzzReader { if (bytes.size() == 0) { bytes.push_back(0); } - build(); + } + + void pickPasses(OptimizationOptions& options) { + while (options.passes.size() < 20 && !oneIn(3)) { + switch (upTo(32)) { + case 0: + case 1: + case 2: + case 3: + case 4: { + options.passes.push_back("O"); + options.passOptions.optimizeLevel = upTo(4); + options.passOptions.shrinkLevel = upTo(4); + break; + } + case 5: options.passes.push_back("coalesce-locals"); break; + case 6: options.passes.push_back("code-pushing"); break; + case 7: options.passes.push_back("code-folding"); break; + case 8: options.passes.push_back("dce"); break; + case 9: options.passes.push_back("duplicate-function-elimination"); break; + case 10: options.passes.push_back("flatten"); break; + case 11: options.passes.push_back("inlining"); break; + case 12: options.passes.push_back("inlining-optimizing"); break; + case 13: options.passes.push_back("local-cse"); break; + case 14: options.passes.push_back("memory-packing"); break; + case 15: options.passes.push_back("merge-blocks"); break; + case 16: options.passes.push_back("optimize-instructions"); break; + case 17: options.passes.push_back("pick-load-signs"); break; + case 18: options.passes.push_back("precompute"); break; + case 19: options.passes.push_back("precompute-propagate"); break; + case 20: options.passes.push_back("remove-unused-brs"); break; + case 21: options.passes.push_back("remove-unused-module-elements"); break; + case 22: options.passes.push_back("remove-unused-names"); break; + case 23: options.passes.push_back("reorder-functions"); break; + case 24: options.passes.push_back("reorder-locals"); break; + case 25: { + options.passes.push_back("flatten"); + options.passes.push_back("rereloop"); + break; + } + case 26: options.passes.push_back("simplify-locals"); break; + case 27: options.passes.push_back("simplify-locals-notee"); break; + case 28: options.passes.push_back("simplify-locals-nostructure"); break; + case 29: options.passes.push_back("simplify-locals-notee-nostructure"); break; + case 30: options.passes.push_back("ssa"); break; + case 31: options.passes.push_back("vacuum"); break; + default: WASM_UNREACHABLE(); + } + } + if (oneIn(2)) { + options.passOptions.optimizeLevel = upTo(4); + } + if (oneIn(2)) { + options.passOptions.shrinkLevel = upTo(4); + } + std::cout << "opt level: " << options.passOptions.optimizeLevel << '\n'; + std::cout << "shrink level: " << options.passOptions.shrinkLevel << '\n'; + } + + void build() { + setupMemory(); + setupTable(); + setupGlobals(); + // keep adding functions until we run out of input + while (!finishedInput) { + addFunction(); + } + if (HANG_LIMIT > 0) { + addHangLimitSupport(); + } + if (DE_NAN) { + addDeNanSupport(); + } + finalizeTable(); } private: @@ -141,23 +212,6 @@ class TranslateToFuzzReader { return Literal(get64()).reinterpretf64(); } - void build() { - setupMemory(); - setupTable(); - setupGlobals(); - // keep adding functions until we run out of input - while (!finishedInput) { - addFunction(); - } - if (HANG_LIMIT > 0) { - addHangLimitSupport(); - } - if (DE_NAN) { - addDeNanSupport(); - } - finalizeTable(); - } - void setupMemory() { wasm.memory.exists = true; // use one page diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 7c2a3a35a1d..bbb41982ec4 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -33,7 +33,7 @@ #include "shell-interface.h" #include "optimization-options.h" #include "execution-results.h" -#include "translate-to-fuzz.h" +#include "fuzzing.h" #include "js-wrapper.h" #include "spec-wrapper.h" @@ -68,6 +68,7 @@ int main(int argc, const char* argv[]) { bool fuzzBinary = false; std::string extraFuzzCommand; bool translateToFuzz = false; + bool fuzzPasses = false; std::string emitJSWrapper; std::string emitSpecWrapper; @@ -97,6 +98,9 @@ int main(int argc, const char* argv[]) { .add("--translate-to-fuzz", "-ttf", "Translate the input into a valid wasm module *somehow*, useful for fuzzing", Options::Arguments::Zero, [&](Options *o, const std::string &arguments) { translateToFuzz = true; }) + .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)", + Options::Arguments::Zero, + [&](Options *o, const std::string &arguments) { fuzzPasses = true; }) .add("--emit-js-wrapper", "-ejw", "Emit a JavaScript wrapper file that can run the wasm with some test values, useful for fuzzing", Options::Arguments::One, [&](Options *o, const std::string &arguments) { emitJSWrapper = arguments; }) @@ -133,8 +137,11 @@ int main(int argc, const char* argv[]) { } } else { // translate-to-fuzz - TranslateToFuzzReader reader(wasm); - reader.read(options.extra["infile"]); + TranslateToFuzzReader reader(wasm, options.extra["infile"]); + if (fuzzPasses) { + reader.pickPasses(options); + } + reader.build(); if (!WasmValidator().validate(wasm, features)) { std::cerr << "translate-to-fuzz must always generate a valid module"; abort(); From f2b9e8f5643b9ac7491bb487feb1db56027c0662 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 30 Oct 2017 14:29:01 -0700 Subject: [PATCH 2/2] when input is finished stop adding passes --- src/tools/fuzzing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index cddd5a3ec07..978d4e44335 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -66,7 +66,7 @@ class TranslateToFuzzReader { } void pickPasses(OptimizationOptions& options) { - while (options.passes.size() < 20 && !oneIn(3)) { + while (options.passes.size() < 20 && !finishedInput && !oneIn(3)) { switch (upTo(32)) { case 0: case 1: