Add corpus based multi source fuzzer

Co-authored-by: Leonardo <leo@ethereum.org>
This commit is contained in:
Bhargava Shastry 2020-07-06 19:32:48 +02:00
parent eab999f753
commit 4067bab7dd
7 changed files with 54 additions and 9 deletions

View File

@ -38,6 +38,13 @@ TestCaseReader::TestCaseReader(string const& _filename):
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
{
if (m_sources.sources.size() != 1)

View File

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

View File

@ -72,16 +72,16 @@ void FuzzerUtil::testCompilerJsonInterface(string const& _input, bool _optimize,
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;
EVMVersion evmVersion = s_evmVersions[_input.size() % s_evmVersions.size()];
EVMVersion evmVersion = s_evmVersions[_rand % s_evmVersions.size()];
frontend::OptimiserSettings optimiserSettings;
if (_optimize)
optimiserSettings = frontend::OptimiserSettings::standard();
else
optimiserSettings = frontend::OptimiserSettings::minimal();
compiler.setSources({{"", _input}});
compiler.setSources(_input);
compiler.setEVMVersion(evmVersion);
compiler.setOptimiserSettings(optimiserSettings);
try

View File

@ -16,6 +16,9 @@
*/
// SPDX-License-Identifier: GPL-3.0
#include <libsolutil/Common.h>
#include <map>
#include <string>
/**
@ -28,5 +31,9 @@ struct FuzzerUtil
static void testCompilerJsonInterface(std::string const& _input, bool _optimize, bool _quiet);
static void testConstantOptimizer(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()
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)
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)
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/TestCaseReader.h>
#include <sstream>
using namespace solidity::frontend::test;
using namespace std;
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)
{
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;
}

View File

@ -18,14 +18,29 @@
#include <test/tools/fuzzer_common.h>
#include <test/TestCaseReader.h>
#include <sstream>
using namespace solidity::frontend::test;
using namespace std;
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
{
if (_size <= 600)
{
string input(reinterpret_cast<char const *>(_data), _size);
FuzzerUtil::testCompiler(input, /*optimize=*/true);
string input(reinterpret_cast<char const*>(_data), _size);
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;
}