diff options
Diffstat (limited to 'test/fuzzer.cpp')
-rw-r--r-- | test/fuzzer.cpp | 137 |
1 files changed, 135 insertions, 2 deletions
diff --git a/test/fuzzer.cpp b/test/fuzzer.cpp index 410313c5..053d880f 100644 --- a/test/fuzzer.cpp +++ b/test/fuzzer.cpp @@ -16,21 +16,32 @@ */ /** * Executable for use with AFL <http://lcamtuf.coredump.cx/afl>. - * Reads a single source from stdin and signals a failure for internal errors. */ +#include <libevmasm/Assembly.h> +#include <libevmasm/ConstantOptimiser.h> + #include <json/json.h> +#include <boost/program_options.hpp> + #include <string> #include <iostream> using namespace std; +using namespace dev; +using namespace dev::eth; +namespace po = boost::program_options; extern "C" { extern char const* compileJSON(char const* _input, bool _optimize); +typedef void (*CStyleReadFileCallback)(char const* _path, char** o_contents, char** o_error); +extern char const* compileStandard(char const* _input, CStyleReadFileCallback _readCallback); } +bool quiet = false; + string contains(string const& _haystack, vector<string> const& _needles) { for (string const& needle: _needles) @@ -39,7 +50,42 @@ string contains(string const& _haystack, vector<string> const& _needles) return ""; } -int main() +void testConstantOptimizer() +{ + if (!quiet) + cout << "Testing constant optimizer" << endl; + vector<u256> numbers; + while (!cin.eof()) + { + h256 data; + cin.read(reinterpret_cast<char*>(data.data()), 32); + numbers.push_back(u256(data)); + } + if (!quiet) + cout << "Got " << numbers.size() << " inputs:" << endl; + + Assembly assembly; + for (u256 const& n: numbers) + { + if (!quiet) + cout << n << endl; + assembly.append(n); + } + for (bool isCreation: {false, true}) + { + for (unsigned runs: {1, 2, 3, 20, 40, 100, 200, 400, 1000}) + { + ConstantOptimisationMethod::optimiseConstants( + isCreation, + runs, + assembly, + const_cast<AssemblyItems&>(assembly.items()) + ); + } + } +} + +string readInput() { string input; while (!cin.eof()) @@ -48,6 +94,41 @@ int main() getline(cin, s); input += s + '\n'; } + return input; +} + +void testStandardCompiler() +{ + if (!quiet) + cout << "Testing compiler via JSON interface." << endl; + string input = readInput(); + string outputString(compileStandard(input.c_str(), NULL)); + Json::Value output; + if (!Json::Reader().parse(outputString, output)) + { + cout << "Compiler produced invalid JSON output." << endl; + abort(); + } + if (output.isMember("errors")) + for (auto const& error: output["errors"]) + { + string invalid = contains(error["type"].asString(), vector<string>{ + "Exception", + "InternalCompilerError" + }); + if (!invalid.empty()) + { + cout << "Invalid error: \"" << error["type"].asString() << "\"" << endl; + abort(); + } + } +} + +void testCompiler() +{ + if (!quiet) + cout << "Testing compiler." << endl; + string input = readInput(); bool optimize = true; string outputString(compileJSON(input.c_str(), optimize)); @@ -87,5 +168,57 @@ int main() cout << "Output JSON has neither \"errors\" nor \"contracts\"." << endl; abort(); } +} + +int main(int argc, char** argv) +{ + po::options_description options( + R"(solfuzzer, fuzz-testing binary for use with AFL. +Usage: solfuzzer [Options] < input +Reads a single source from stdin, compiles it and signals a failure for internal errors. + +Allowed options)", + po::options_description::m_default_line_length, + po::options_description::m_default_line_length - 23); + options.add_options() + ("help", "Show this help screen.") + ("quiet", "Only output errors.") + ( + "standard-json", + "Test via the standard-json interface, i.e. " + "input is expected to be JSON-encoded instead of " + "plain source file." + ) + ( + "const-opt", + "Run the constant optimizer instead of compiling. " + "Expects a binary string of up to 32 bytes on stdin." + ); + + po::variables_map arguments; + try + { + po::command_line_parser cmdLineParser(argc, argv); + cmdLineParser.options(options); + po::store(cmdLineParser.run(), arguments); + } + catch (po::error const& _exception) + { + cerr << _exception.what() << endl; + return 1; + } + + if (arguments.count("quiet")) + quiet = true; + + if (arguments.count("help")) + cout << options; + else if (arguments.count("const-opt")) + testConstantOptimizer(); + else if (arguments.count("standard-json")) + testStandardCompiler(); + else + testCompiler(); + return 0; } |