summaryrefslogtreecommitdiff
path: root/src/tools/wasm-opt.cpp
diff options
context:
space:
mode:
authorAlon Zakai (kripken) <alonzakai@gmail.com>2017-05-20 21:13:52 -0700
committerAlon Zakai (kripken) <alonzakai@gmail.com>2017-05-20 21:13:52 -0700
commit026accbe55dde6b9d769292195c3ad1ac0a3b8b0 (patch)
treee26a0fd5865003a7a18ab8735ff6411fc2bf465f /src/tools/wasm-opt.cpp
parent2f3bcb914b55f469426418fed1d85e00d0e4db1b (diff)
downloadbinaryen-026accbe55dde6b9d769292195c3ad1ac0a3b8b0.tar.gz
binaryen-026accbe55dde6b9d769292195c3ad1ac0a3b8b0.tar.bz2
binaryen-026accbe55dde6b9d769292195c3ad1ac0a3b8b0.zip
add --fuzz-exec option to wasm-opt, which (when possible) executes results before and after optimizations are run, checking for changes. this can be used when fuzzing
Diffstat (limited to 'src/tools/wasm-opt.cpp')
-rw-r--r--src/tools/wasm-opt.cpp73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp
index bf79cb31d..468f3ce93 100644
--- a/src/tools/wasm-opt.cpp
+++ b/src/tools/wasm-opt.cpp
@@ -28,9 +28,64 @@
#include "wasm-s-parser.h"
#include "wasm-validator.h"
#include "wasm-io.h"
+#include "wasm-interpreter.h"
+#include "shell-interface.h"
using namespace wasm;
+// gets execution results from a wasm module. this is useful for fuzzing
+//
+// we can only get results when there are no imports. we then call each method
+// that has a result, with some values
+struct ExecutionResults {
+ std::map<Name, Literal> results;
+
+ void get(Module& wasm) {
+ if (wasm.imports.size() > 0) {
+ std::cout << "[fuzz-exec] imports, so quitting\n";
+ return;
+ }
+ for (auto& func : wasm.functions) {
+ if (func->result != none) {
+ // this is good
+ results[func->name] = run(func.get(), wasm);
+ }
+ }
+ std::cout << "[fuzz-exec] " << results.size() << " results noted\n";
+ }
+
+ bool operator==(ExecutionResults& other) {
+ for (auto& iter : results) {
+ auto name = iter.first;
+ if (other.results.find(name) != other.results.end()) {
+ if (results[name] != other.results[name]) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ bool operator!=(ExecutionResults& other) {
+ return !((*this) == other);
+ }
+
+ Literal run(Function* func, Module& wasm) {
+ ShellExternalInterface interface;
+ ModuleInstance instance(wasm, &interface);
+ LiteralList arguments;
+ for (WasmType param : func->params) {
+ // zeros in arguments TODO: more?
+ arguments.push_back(Literal(param));
+ }
+ try {
+ return instance.callFunctionInternal(func->name, arguments);
+ } catch (const TrapException&) {
+ return Literal();
+ }
+ }
+};
+
//
// main
//
@@ -42,6 +97,7 @@ int main(int argc, const char* argv[]) {
PassOptions passOptions;
bool emitBinary = true;
bool debugInfo = false;
+ bool fuzzExec = false;
Options options("wasm-opt", "Optimize .wast files");
options
@@ -58,6 +114,9 @@ int main(int argc, const char* argv[]) {
.add("--debuginfo", "-g", "Emit names section and debug info",
Options::Arguments::Zero,
[&](Options *o, const std::string &arguments) { debugInfo = true; })
+ .add("--fuzz-exec", "-fe", "Execute functions before and after optimization, helping fuzzing find bugs",
+ Options::Arguments::Zero,
+ [&](Options *o, const std::string &arguments) { fuzzExec = true; })
.add_positional("INFILE", Options::Arguments::One,
[](Options* o, const std::string& argument) {
o->extra["infile"] = argument;
@@ -99,6 +158,11 @@ int main(int argc, const char* argv[]) {
Fatal() << "error in validating input";
}
+ ExecutionResults results;
+ if (fuzzExec) {
+ results.get(wasm);
+ }
+
if (passes.size() > 0) {
if (options.debug) std::cerr << "running passes...\n";
PassRunner passRunner(&wasm, passOptions);
@@ -114,6 +178,15 @@ int main(int argc, const char* argv[]) {
assert(WasmValidator().validate(wasm));
}
+ if (fuzzExec) {
+ ExecutionResults optimizedResults;
+ optimizedResults.get(wasm);
+ if (optimizedResults != results) {
+ Fatal() << "[fuzz-exec] optimization passes changed execution results";
+ }
+ std::cout << "[fuzz-exec] results match\n";
+ }
+
if (options.extra.count("output") > 0) {
if (options.debug) std::cerr << "writing..." << std::endl;
ModuleWriter writer;