yul proto fuzzer: Catch exception early and propagate termination reason to harness

This commit is contained in:
Bhargava Shastry 2019-11-01 11:36:29 +01:00
parent 1bd2b202e9
commit e4ba1c02e8
4 changed files with 55 additions and 58 deletions

View File

@ -78,35 +78,21 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
ostringstream os1;
ostringstream os2;
try
{
yulFuzzerUtil::interpret(
os1,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion())
);
}
catch (yul::test::StepLimitReached const&)
{
yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret(
os1,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion())
);
if (termReason == yulFuzzerUtil::TerminationReason::StepLimitReached)
return 0;
}
catch (yul::test::InterpreterTerminatedGeneric const&)
{
}
stack.optimize();
try
{
yulFuzzerUtil::interpret(
os2,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()),
(yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 1.5)
);
}
catch (yul::test::InterpreterTerminatedGeneric const&)
{
}
termReason = yulFuzzerUtil::interpret(
os2,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()),
(yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 1.5)
);
bool isTraceEq = (os1.str() == os2.str());
yulAssert(isTraceEq, "Interpreted traces for optimized and unoptimized code differ.");

View File

@ -20,7 +20,7 @@ using namespace std;
using namespace yul;
using namespace yul::test::yul_fuzzer;
void yulFuzzerUtil::interpret(
yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret(
ostream& _os,
shared_ptr<yul::Block> _ast,
Dialect const& _dialect,
@ -44,6 +44,25 @@ void yulFuzzerUtil::interpret(
0x8e, 0xf3, 0x9b, 0xe4, 0x4f, 0x6c, 0x14, 0xde
};
Interpreter interpreter(state, _dialect);
interpreter(*_ast);
TerminationReason reason = TerminationReason::None;
try
{
interpreter(*_ast);
}
catch (StepLimitReached const&)
{
reason = TerminationReason::StepLimitReached;
}
catch (TraceLimitReached const&)
{
reason = TerminationReason::TraceLimitReached;
}
catch (ExplicitlyTerminated const&)
{
reason = TerminationReason::ExplicitlyTerminated;
}
state.dumpTraceAndState(_os);
return reason;
}

View File

@ -25,7 +25,15 @@ namespace yul_fuzzer
{
struct yulFuzzerUtil
{
static void interpret(
enum class TerminationReason
{
ExplicitlyTerminated,
StepLimitReached,
TraceLimitReached,
None
};
static TerminationReason interpret(
std::ostream& _os,
std::shared_ptr<yul::Block> _ast,
Dialect const& _dialect,

View File

@ -66,9 +66,6 @@ DEFINE_PROTO_FUZZER(Program const& _input)
of.write(yul_source.data(), yul_source.size());
}
if (yul_source.size() > 1200)
return;
YulStringRepository::reset();
// AssemblyStack entry point
@ -95,35 +92,22 @@ DEFINE_PROTO_FUZZER(Program const& _input)
ostringstream os1;
ostringstream os2;
try
{
yulFuzzerUtil::interpret(
os1,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion())
);
}
catch (yul::test::StepLimitReached const&)
{
yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret(
os1,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion())
);
if (termReason == yulFuzzerUtil::TerminationReason::StepLimitReached)
return;
}
catch (yul::test::InterpreterTerminatedGeneric const&)
{
}
stack.optimize();
try
{
yulFuzzerUtil::interpret(
os2,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()),
(yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 1.5)
);
}
catch (yul::test::InterpreterTerminatedGeneric const&)
{
}
termReason = yulFuzzerUtil::interpret(
os2,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()),
(yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 1.5)
);
bool isTraceEq = (os1.str() == os2.str());
yulAssert(isTraceEq, "Interpreted traces for optimized and unoptimized code differ.");