From bbda89c42810cad57c92bd30f4cebd51fd2c413a Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 6 Feb 2018 10:57:16 +0100 Subject: [PATCH] Create a differential fuzzer using tracing facility from the yul interpreter. --- test/tools/ossfuzz/CMakeLists.txt | 10 ++- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 74 +++++++++++++++++++ test/tools/ossfuzz/yulFuzzerCommon.cpp | 39 ++++++++++ test/tools/ossfuzz/yulFuzzerCommon.h | 31 ++++++++ 4 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp create mode 100644 test/tools/ossfuzz/yulFuzzerCommon.cpp create mode 100644 test/tools/ossfuzz/yulFuzzerCommon.h diff --git a/test/tools/ossfuzz/CMakeLists.txt b/test/tools/ossfuzz/CMakeLists.txt index 6a32c0eb5..bed8762c2 100644 --- a/test/tools/ossfuzz/CMakeLists.txt +++ b/test/tools/ossfuzz/CMakeLists.txt @@ -1,5 +1,10 @@ add_custom_target(ossfuzz) -add_dependencies(ossfuzz solc_opt_ossfuzz solc_noopt_ossfuzz const_opt_ossfuzz) +add_dependencies(ossfuzz + solc_opt_ossfuzz + solc_noopt_ossfuzz + const_opt_ossfuzz + strictasm_diff_ossfuzz + ) #[[FuzzingEngine.a is provided by oss-fuzz's Dockerized build environment]] add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp) @@ -10,3 +15,6 @@ target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm FuzzingEngine.a) add_executable(const_opt_ossfuzz const_opt_ossfuzz.cpp ../fuzzer_common.cpp) target_link_libraries(const_opt_ossfuzz PRIVATE libsolc evmasm FuzzingEngine.a) + +add_executable(strictasm_diff_ossfuzz strictasm_diff_ossfuzz.cpp yulFuzzerCommon.cpp) +target_link_libraries(strictasm_diff_ossfuzz PRIVATE libsolc evmasm yulInterpreter FuzzingEngine.a) \ No newline at end of file diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp new file mode 100644 index 000000000..882f35462 --- /dev/null +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -0,0 +1,74 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +using namespace yul; +using namespace std; + +using namespace langutil; +using namespace dev; +using namespace yul::test::yul_fuzzer; + +extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) +{ + if (_size > 600) + return 0; + + string input(reinterpret_cast(_data), _size); + + AssemblyStack stack(EVMVersion::petersburg(), AssemblyStack::Language::StrictAssembly); + try + { + if (!stack.parseAndAnalyze("source", input) || !stack.parserResult()->code || + !stack.parserResult()->analysisInfo) + return 0; + } + catch (Exception const&) + { + return 0; + } + + ostringstream os1; + ostringstream os2; + yulFuzzerUtil::interpret(os1, stack.parserResult()->code); + stack.optimize(); + yulFuzzerUtil::interpret(os2, stack.parserResult()->code); + + bool isTraceEq = (os1.str() == os2.str()); + yulAssert(isTraceEq, "Interpreted traces for optimized and unoptimized code differ."); + return 0; +} diff --git a/test/tools/ossfuzz/yulFuzzerCommon.cpp b/test/tools/ossfuzz/yulFuzzerCommon.cpp new file mode 100644 index 000000000..b5a8eba80 --- /dev/null +++ b/test/tools/ossfuzz/yulFuzzerCommon.cpp @@ -0,0 +1,39 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +#include + +using namespace std; +using namespace yul; +using namespace yul::test::yul_fuzzer; + +void yulFuzzerUtil::interpret(ostream& _os, shared_ptr _ast) +{ + InterpreterState state; + state.maxTraceSize = 10000; + Interpreter interpreter(state); + try + { + interpreter(*_ast); + } + catch (InterpreterTerminated const&) + { + } + + _os << "Trace:" << endl; + for (auto const& line: interpreter.trace()) + _os << " " << line << endl; +} \ No newline at end of file diff --git a/test/tools/ossfuzz/yulFuzzerCommon.h b/test/tools/ossfuzz/yulFuzzerCommon.h new file mode 100644 index 000000000..26b472b9c --- /dev/null +++ b/test/tools/ossfuzz/yulFuzzerCommon.h @@ -0,0 +1,31 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +#include + +namespace yul +{ +namespace test +{ +namespace yul_fuzzer +{ +struct yulFuzzerUtil +{ + static void interpret(std::ostream& _os, std::shared_ptr _ast); +}; +} +} +}