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 os1;
ostringstream os2; ostringstream os2;
try yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret(
{ os1,
yulFuzzerUtil::interpret( stack.parserResult()->code,
os1, EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion())
stack.parserResult()->code, );
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()) if (termReason == yulFuzzerUtil::TerminationReason::StepLimitReached)
);
}
catch (yul::test::StepLimitReached const&)
{
return 0; return 0;
}
catch (yul::test::InterpreterTerminatedGeneric const&)
{
}
stack.optimize(); stack.optimize();
try termReason = yulFuzzerUtil::interpret(
{ os2,
yulFuzzerUtil::interpret( stack.parserResult()->code,
os2, EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()),
stack.parserResult()->code, (yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 1.5)
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), );
(yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 1.5)
);
}
catch (yul::test::InterpreterTerminatedGeneric const&)
{
}
bool isTraceEq = (os1.str() == os2.str()); bool isTraceEq = (os1.str() == os2.str());
yulAssert(isTraceEq, "Interpreted traces for optimized and unoptimized code differ."); 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;
using namespace yul::test::yul_fuzzer; using namespace yul::test::yul_fuzzer;
void yulFuzzerUtil::interpret( yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret(
ostream& _os, ostream& _os,
shared_ptr<yul::Block> _ast, shared_ptr<yul::Block> _ast,
Dialect const& _dialect, Dialect const& _dialect,
@ -44,6 +44,25 @@ void yulFuzzerUtil::interpret(
0x8e, 0xf3, 0x9b, 0xe4, 0x4f, 0x6c, 0x14, 0xde 0x8e, 0xf3, 0x9b, 0xe4, 0x4f, 0x6c, 0x14, 0xde
}; };
Interpreter interpreter(state, _dialect); 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); state.dumpTraceAndState(_os);
return reason;
} }

View File

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

View File

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