This commit is contained in:
Bhargava Shastry 2020-08-13 13:32:26 +02:00
parent 3045770a6f
commit 68146e7c28
5 changed files with 117 additions and 5 deletions

View File

@ -29,6 +29,11 @@
#include <liblangutil/Exceptions.h>
#include <libyul/AssemblyStack.h>
#include <test/tools/ossfuzz/yulFuzzerCommon.h>
#include <liblangutil/SourceReferenceFormatter.h>
#include <sstream>
using namespace std;
@ -36,6 +41,22 @@ using namespace solidity;
using namespace solidity::util;
using namespace solidity::evmasm;
using namespace solidity::langutil;
using namespace solidity::yul;
using namespace solidity::yul::test::yul_fuzzer;
namespace
{
void printErrors(ostream& _stream, ErrorList const& _errors)
{
SourceReferenceFormatter formatter(_stream);
for (auto const& error: _errors)
formatter.printExceptionInformation(
*error,
(error->type() == Error::Type::Warning) ? "Warning" : "Error"
);
}
}
static vector<EVMVersion> s_evmVersions = {
EVMVersion::homestead(),
@ -81,6 +102,73 @@ void FuzzerUtil::forceSMT(StringMap& _input)
sourceUnit.second += smtPragma;
}
void FuzzerUtil::yulIRDiff(EVMVersion _version, string const& _ir, string const& _irOpt)
{
YulStringRepository::reset();
if (_ir.empty() && _irOpt.empty())
return;
// AssemblyStack entry point
AssemblyStack stackIr(
_version,
AssemblyStack::Language::StrictAssembly,
solidity::frontend::OptimiserSettings::full()
);
// Parse protobuf mutated YUL code
if (
!stackIr.parseAndAnalyze("source", _ir) ||
!stackIr.parserResult()->code ||
!stackIr.parserResult()->analysisInfo ||
!Error::containsOnlyWarnings(stackIr.errors())
)
{
std::cout << _ir << std::endl;
printErrors(std::cout, stackIr.errors());
yulAssert(false, "Compiler generated malformed IR");
}
AssemblyStack stackIrOpt(
_version,
AssemblyStack::Language::StrictAssembly,
solidity::frontend::OptimiserSettings::full()
);
// Parse protobuf mutated YUL code
if (
!stackIrOpt.parseAndAnalyze("source", _irOpt) ||
!stackIrOpt.parserResult()->code ||
!stackIrOpt.parserResult()->analysisInfo ||
!Error::containsOnlyWarnings(stackIrOpt.errors())
)
{
std::cout << _irOpt << std::endl;
printErrors(std::cout, stackIrOpt.errors());
yulAssert(false, "Compiler generated malformed optimized IR");
}
ostringstream os1;
ostringstream os2;
yulFuzzerUtil::interpret(
os1,
stackIr.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(_version)
);
yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret(
os2,
stackIrOpt.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(_version)
);
if (termReason == yulFuzzerUtil::TerminationReason::StepLimitReached)
return;
bool isTraceEq = (os1.str() == os2.str());
yulAssert(isTraceEq, "Interpreted traces for optimized and unoptimized code differ.");
}
void FuzzerUtil::testCompiler(StringMap& _input, bool _optimize, unsigned _rand, bool _forceSMT)
{
frontend::CompilerStack compiler;
@ -96,11 +184,23 @@ void FuzzerUtil::testCompiler(StringMap& _input, bool _optimize, unsigned _rand,
compiler.setModelCheckerSettings({frontend::ModelCheckerEngine::All(), frontend::ModelCheckerTargets::All(), /*timeout=*/1});
}
compiler.setSources(_input);
compiler.enableIRGeneration();
compiler.setEVMVersion(evmVersion);
compiler.setOptimiserSettings(optimiserSettings);
try
{
compiler.compile();
if (compiler.compile() && !compiler.contractNames().empty())
{
string lastContractName = compiler.lastContractName();
yulIRDiff(
evmVersion,
compiler.yulIR(lastContractName),
compiler.yulIROptimized(lastContractName)
);
}
}
catch (InternalCompilerError const&)
{
}
catch (Error const&)
{

View File

@ -18,6 +18,7 @@
#include <libsolutil/Common.h>
#include <liblangutil/EVMVersion.h>
#include <map>
#include <string>
@ -46,4 +47,5 @@ struct FuzzerUtil
/// Adds the experimental SMTChecker pragma to each source file in the
/// source map.
static void forceSMT(solidity::StringMap& _input);
static void yulIRDiff(solidity::langutil::EVMVersion _version, std::string const& _ir, std::string const& _irOpt);
};

View File

@ -28,8 +28,13 @@ if (OSSFUZZ)
solc_opt_ossfuzz.cpp
../fuzzer_common.cpp
../../TestCaseReader.cpp
yulFuzzerCommon.cpp
)
target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm)
target_compile_options(solc_opt_ossfuzz
PUBLIC
${COMPILE_OPTIONS} -Wno-extra-semi -Wno-unused-parameter
)
target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm yul yulInterpreter)
set_target_properties(solc_opt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
add_executable(solc_opt_mutator_ossfuzz
@ -46,8 +51,13 @@ if (OSSFUZZ)
solc_noopt_ossfuzz.cpp
../fuzzer_common.cpp
../../TestCaseReader.cpp
yulFuzzerCommon.cpp
)
target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm)
target_compile_options(solc_noopt_ossfuzz
PUBLIC
${COMPILE_OPTIONS} -Wno-extra-semi -Wno-unused-parameter
)
target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm yul yulInterpreter)
set_target_properties(solc_noopt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
add_executable(solc_noopt_mutator_ossfuzz

View File

@ -30,7 +30,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size);
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
{
if (_size <= 600)
if (_size <= 4096)
{
string input(reinterpret_cast<char const*>(_data), _size);
map<string, string> sourceCode;

View File

@ -40,7 +40,7 @@ struct yulFuzzerUtil
size_t _maxTraceSize = maxTraceSize,
size_t _maxExprNesting = maxExprNesting
);
static size_t constexpr maxSteps = 100;
static size_t constexpr maxSteps = 10000000;
static size_t constexpr maxTraceSize = 75;
static size_t constexpr maxExprNesting = 64;
};