summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/translate-to-fuzz.h18
-rw-r--r--src/tools/wasm-opt.cpp69
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();
+ }
+ }
}
}