Merge pull request #9446 from ethereum/fix-9445

Add corpus based multi source fuzzer
This commit is contained in:
chriseth 2020-07-21 14:44:57 +02:00 committed by GitHub
commit f4b912fffa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 54 additions and 9 deletions

View File

@ -38,6 +38,13 @@ TestCaseReader::TestCaseReader(string const& _filename):
m_unreadSettings = m_settings; m_unreadSettings = m_settings;
} }
TestCaseReader::TestCaseReader(istringstream const& _str)
{
tie(m_sources, m_lineNumber) = parseSourcesAndSettingsWithLineNumber(
static_cast<istream&>(const_cast<istringstream&>(_str))
);
}
string const& TestCaseReader::source() const string const& TestCaseReader::source() const
{ {
if (m_sources.sources.size() != 1) if (m_sources.sources.size() != 1)

View File

@ -42,6 +42,7 @@ class TestCaseReader
public: public:
TestCaseReader() = default; TestCaseReader() = default;
explicit TestCaseReader(std::string const& _filename); explicit TestCaseReader(std::string const& _filename);
explicit TestCaseReader(std::istringstream const& _testCode);
SourceMap const& sources() const { return m_sources; } SourceMap const& sources() const { return m_sources; }
std::string const& source() const; std::string const& source() const;

View File

@ -72,16 +72,16 @@ void FuzzerUtil::testCompilerJsonInterface(string const& _input, bool _optimize,
runCompiler(jsonCompactPrint(config), _quiet); runCompiler(jsonCompactPrint(config), _quiet);
} }
void FuzzerUtil::testCompiler(string const& _input, bool _optimize) void FuzzerUtil::testCompiler(StringMap const& _input, bool _optimize, unsigned _rand)
{ {
frontend::CompilerStack compiler; frontend::CompilerStack compiler;
EVMVersion evmVersion = s_evmVersions[_input.size() % s_evmVersions.size()]; EVMVersion evmVersion = s_evmVersions[_rand % s_evmVersions.size()];
frontend::OptimiserSettings optimiserSettings; frontend::OptimiserSettings optimiserSettings;
if (_optimize) if (_optimize)
optimiserSettings = frontend::OptimiserSettings::standard(); optimiserSettings = frontend::OptimiserSettings::standard();
else else
optimiserSettings = frontend::OptimiserSettings::minimal(); optimiserSettings = frontend::OptimiserSettings::minimal();
compiler.setSources({{"", _input}}); compiler.setSources(_input);
compiler.setEVMVersion(evmVersion); compiler.setEVMVersion(evmVersion);
compiler.setOptimiserSettings(optimiserSettings); compiler.setOptimiserSettings(optimiserSettings);
try try

View File

@ -16,6 +16,9 @@
*/ */
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
#include <libsolutil/Common.h>
#include <map>
#include <string> #include <string>
/** /**
@ -28,5 +31,9 @@ struct FuzzerUtil
static void testCompilerJsonInterface(std::string const& _input, bool _optimize, bool _quiet); static void testCompilerJsonInterface(std::string const& _input, bool _optimize, bool _quiet);
static void testConstantOptimizer(std::string const& _input, bool _quiet); static void testConstantOptimizer(std::string const& _input, bool _quiet);
static void testStandardCompiler(std::string const& _input, bool _quiet); static void testStandardCompiler(std::string const& _input, bool _quiet);
static void testCompiler(std::string const& _input, bool _optimize); /// Compiles @param _input which is a map of input file name to source code
/// string with optimisation turned on if @param _optimize is true
/// (off otherwise) and a pseudo-random @param _rand that selects the EVM
/// version to be compiled for.
static void testCompiler(solidity::StringMap const& _input, bool _optimize, unsigned _rand);
}; };

View File

@ -23,11 +23,11 @@ if (OSSFUZZ)
endif() endif()
if (OSSFUZZ) if (OSSFUZZ)
add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp) add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp ../../TestCaseReader.cpp)
target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm) target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm)
set_target_properties(solc_opt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) set_target_properties(solc_opt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
add_executable(solc_noopt_ossfuzz solc_noopt_ossfuzz.cpp ../fuzzer_common.cpp) add_executable(solc_noopt_ossfuzz solc_noopt_ossfuzz.cpp ../fuzzer_common.cpp ../../TestCaseReader.cpp)
target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm) target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm)
set_target_properties(solc_noopt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) set_target_properties(solc_noopt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})

View File

@ -18,6 +18,11 @@
#include <test/tools/fuzzer_common.h> #include <test/tools/fuzzer_common.h>
#include <test/TestCaseReader.h>
#include <sstream>
using namespace solidity::frontend::test;
using namespace std; using namespace std;
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
@ -25,7 +30,17 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
if (_size <= 600) if (_size <= 600)
{ {
string input(reinterpret_cast<char const*>(_data), _size); string input(reinterpret_cast<char const*>(_data), _size);
FuzzerUtil::testCompiler(input, /*optimize=*/false); map<string, string> sourceCode;
try
{
TestCaseReader t = TestCaseReader(std::istringstream(input));
sourceCode = t.sources().sources;
}
catch (runtime_error const&)
{
return 0;
}
FuzzerUtil::testCompiler(sourceCode, /*optimize=*/false, /*_rand=*/_size);
} }
return 0; return 0;
} }

View File

@ -18,6 +18,11 @@
#include <test/tools/fuzzer_common.h> #include <test/tools/fuzzer_common.h>
#include <test/TestCaseReader.h>
#include <sstream>
using namespace solidity::frontend::test;
using namespace std; using namespace std;
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
@ -25,7 +30,17 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
if (_size <= 600) if (_size <= 600)
{ {
string input(reinterpret_cast<char const*>(_data), _size); string input(reinterpret_cast<char const*>(_data), _size);
FuzzerUtil::testCompiler(input, /*optimize=*/true); map<string, string> sourceCode;
try
{
TestCaseReader t = TestCaseReader(std::istringstream(input));
sourceCode = t.sources().sources;
}
catch (runtime_error const&)
{
return 0;
}
FuzzerUtil::testCompiler(sourceCode, /*optimize=*/true, /*rand=*/_size);
} }
return 0; return 0;
} }