diff options
author | Alon Zakai <alonzakai@gmail.com> | 2018-11-30 09:54:57 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-30 09:54:57 -0800 |
commit | 0e068c386ef1588c09e57a4d081be626d83bc31c (patch) | |
tree | 0a432d17fd6a26b6cce092ab81558aeb4270da77 /src/tools/fuzzing.h | |
parent | f16a7605b8226502062c6ca24323d431669c90ec (diff) | |
download | binaryen-0e068c386ef1588c09e57a4d081be626d83bc31c.tar.gz binaryen-0e068c386ef1588c09e57a4d081be626d83bc31c.tar.bz2 binaryen-0e068c386ef1588c09e57a4d081be626d83bc31c.zip |
Fuzzing: log values during execution (#1779)
Before we just looked at function return values when looking for differences before and after running some passes, while fuzzing. This adds logging of values during execution, which can represent control flow, monitor locals, etc., giving a lot more opportunities for the fuzzer to find problems.
Also:
* Clean up the sigToFunctionType function, which allocated a struct and returned it. This makes it safer by returning the struct by value, which is also easier to use in this PR.
* Fix printing of imported function calls without a function type - turns out we always generate function types in loading, so we didn't notice this was broken, but this new fuzzer feature hit it.
Diffstat (limited to 'src/tools/fuzzing.h')
-rw-r--r-- | src/tools/fuzzing.h | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 3b1a418b5..7954229c7 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -128,6 +128,7 @@ public: setupMemory(); setupTable(); setupGlobals(); + addImportLoggingSupport(); // keep adding functions until we run out of input while (!finishedInput) { auto* func = addFunction(); @@ -184,10 +185,13 @@ private: // Whether to emit atomic waits (which in single-threaded mode, may hang...) static const bool ATOMIC_WAITS = false; - // after we finish the input, we start going through it again, but xoring + // After we finish the input, we start going through it again, but xoring // so it's not identical int xorFactor = 0; + // The chance to emit a logging operation for a none expression. We + // randomize this in each function. + unsigned LOGGING_PERCENT = 0; void readData(std::vector<char> input) { bytes.swap(input); @@ -300,6 +304,19 @@ private: wasm.addExport(export_); } + void addImportLoggingSupport() { + for (auto type : { i32, i64, f32, f64 }) { + auto* func = new Function; + Name name = std::string("log-") + printType(type); + func->name = name; + func->module = "fuzzing-support"; + func->base = name; + func->params.push_back(type); + func->result = none; + wasm.addFunction(func); + } + } + Expression* makeHangLimitCheck() { return builder.makeSequence( builder.makeIf( @@ -364,6 +381,7 @@ private: std::map<Type, std::vector<Index>> typeLocals; // type => list of locals with that type Function* addFunction() { + LOGGING_PERCENT = upToSquared(100); Index num = wasm.functions.size(); func = new Function; func->name = std::string("func_") + std::to_string(num); @@ -711,6 +729,8 @@ private: Expression* _makenone() { auto choice = upTo(100); + if (choice < LOGGING_PERCENT) return makeLogging(); + choice = upTo(100); if (choice < 50) return makeSetLocal(none); if (choice < 60) return makeBlock(none); if (choice < 70) return makeIf(none); @@ -1496,6 +1516,13 @@ private: } } + // special makers + + Expression* makeLogging() { + auto type = pick(i32, i64, f32, f64); + return builder.makeCall(std::string("log-") + printType(type), { make(type) }, none); + } + // special getters Type getType() { |