diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/translate-to-fuzz.h | 18 | ||||
-rw-r--r-- | src/tools/wasm-opt.cpp | 69 |
2 files changed, 68 insertions, 19 deletions
diff --git a/src/tools/translate-to-fuzz.h b/src/tools/translate-to-fuzz.h index a7f86af13..307604af6 100644 --- a/src/tools/translate-to-fuzz.h +++ b/src/tools/translate-to-fuzz.h @@ -87,7 +87,7 @@ private: // the number of runtime iterations (function calls, loop backbranches) we // allow before we stop execution with a trap, to prevent hangs. 0 means // no hang protection. - static const int HANG_LIMIT = 25; + static const int HANG_LIMIT = 100; // Optionally remove NaNs, which are a source of nondeterminism (which makes // cross-VM comparisons harder) @@ -452,14 +452,20 @@ private: // make something with no chance of infinite recursion Expression* makeTrivial(WasmType type) { if (isConcreteWasmType(type)) { - return makeConst(type); + if (oneIn(2)) { + return makeGetLocal(type); + } else { + return makeConst(type); + } } else if (type == none) { return makeNop(type); } assert(type == unreachable); - return builder.makeReturn( - isConcreteWasmType(func->result) ? makeConst(func->result) : nullptr - ); + Expression* ret = nullptr; + if (isConcreteWasmType(func->result)) { + ret = makeTrivial(func->result); + } + return builder.makeReturn(ret); } // specific expression creators @@ -650,7 +656,7 @@ private: Expression* makeGetLocal(WasmType type) { auto& locals = typeLocals[type]; - if (locals.empty()) return makeTrivial(type); + if (locals.empty()) return makeConst(type); return builder.makeGetLocal(vectorPick(locals), type); } diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index c34331366..a66bc612f 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -39,6 +39,23 @@ using namespace wasm; +// runs a command and returns its output TODO: portability, return code checking +std::string runCommand(std::string command) { +#ifdef __linux__ + std::string output; + const int MAX_BUFFER = 1024; + char buffer[MAX_BUFFER]; + FILE *stream = popen(command.c_str(), "r"); + while (fgets(buffer, MAX_BUFFER, stream) != NULL) { + output.append(buffer); + } + pclose(stream); + return output; +#else + Fatal() << "TODO: portability for wasm-opt runCommand"; +#endif +} + // // main // @@ -50,6 +67,7 @@ int main(int argc, const char* argv[]) { bool debugInfo = false; bool fuzzExec = false; bool fuzzBinary = false; + std::string extraFuzzCommand; bool translateToFuzz = false; std::string emitJSWrapper; std::string emitSpecWrapper; @@ -74,6 +92,9 @@ int main(int argc, const char* argv[]) { .add("--fuzz-binary", "-fb", "Convert to binary and back after optimizations and before fuzz-exec, helping fuzzing find binary format bugs", Options::Arguments::Zero, [&](Options *o, const std::string &arguments) { fuzzBinary = true; }) + .add("--extra-fuzz-command", "-efc", "An extra command to run on the output before and after optimizing. The output is compared between the two, and an error occurs if they are not equal", + Options::Arguments::One, + [&](Options *o, const std::string &arguments) { extraFuzzCommand = arguments; }) .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; }) @@ -123,6 +144,33 @@ int main(int argc, const char* argv[]) { results.get(wasm); } + if (emitJSWrapper.size() > 0) { + std::ofstream outfile; + outfile.open(emitJSWrapper, std::ofstream::out); + outfile << generateJSWrapper(wasm); + outfile.close(); + } + + if (emitSpecWrapper.size() > 0) { + std::ofstream outfile; + outfile.open(emitSpecWrapper, std::ofstream::out); + outfile << generateSpecWrapper(wasm); + outfile.close(); + } + + std::string firstOutput; + + if (extraFuzzCommand.size() > 0 && options.extra.count("output") > 0) { + if (options.debug) std::cerr << "writing binary before opts, for extra fuzz command..." << std::endl; + ModuleWriter writer; + writer.setDebug(options.debug); + writer.setBinary(emitBinary); + writer.setDebugInfo(debugInfo); + writer.write(wasm, options.extra["output"]); + firstOutput = runCommand(extraFuzzCommand); + std::cout << "[extra-fuzz-command first output:]\n" << firstOutput << '\n'; + } + if (options.runningPasses()) { if (options.debug) std::cerr << "running passes...\n"; PassRunner passRunner = options.getPassRunner(wasm); @@ -155,19 +203,14 @@ int main(int argc, const char* argv[]) { writer.setBinary(emitBinary); writer.setDebugInfo(debugInfo); writer.write(wasm, options.extra["output"]); - } - - if (emitJSWrapper.size() > 0) { - std::ofstream outfile; - outfile.open(emitJSWrapper, std::ofstream::out); - outfile << generateJSWrapper(wasm); - outfile.close(); - } - if (emitSpecWrapper.size() > 0) { - std::ofstream outfile; - outfile.open(emitSpecWrapper, std::ofstream::out); - outfile << generateSpecWrapper(wasm); - outfile.close(); + if (extraFuzzCommand.size() > 0) { + auto secondOutput = runCommand(extraFuzzCommand); + std::cout << "[extra-fuzz-command second output:]\n" << firstOutput << '\n'; + if (firstOutput != secondOutput) { + std::cerr << "extra fuzz command output differs\n"; + abort(); + } + } } } |