Merge pull request #7607 from ethereum/add-leave

yul proto: Add leave statement
This commit is contained in:
chriseth 2019-11-01 13:33:40 +01:00 committed by GitHub
commit 106d8ec3b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 58 deletions

View File

@ -1091,6 +1091,10 @@ void ProtoConverter::visit(Statement const& _x)
case Statement::kPop:
visit(_x.pop());
break;
case Statement::kLeave:
if (m_inFunctionDef)
visit(_x.leave());
break;
case Statement::STMT_ONEOF_NOT_SET:
break;
}
@ -1384,6 +1388,11 @@ void ProtoConverter::visit(PopStmt const& _x)
m_output << ")\n";
}
void ProtoConverter::visit(LeaveStmt const&)
{
m_output << "leave\n";
}
string ProtoConverter::getObjectIdentifier(ObjectId const& _x)
{
unsigned currentId = currentObjectId();

View File

@ -90,6 +90,7 @@ private:
void visit(FunctionCall const&);
void visit(FunctionDef const&);
void visit(PopStmt const&);
void visit(LeaveStmt const&);
void visit(LowLevelCall const&);
void visit(Create const&);
void visit(UnaryOpData const&);

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 * 4)
);
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

@ -359,6 +359,8 @@ message PopStmt {
required Expression expr = 1;
}
message LeaveStmt {}
message Statement {
oneof stmt_oneof {
VarDecl decl = 1;
@ -378,6 +380,7 @@ message Statement {
BoundedForStmt boundedforstmt = 15;
FunctionDef funcdef = 16;
PopStmt pop = 17;
LeaveStmt leave = 18;
}
}

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 * 4)
);
bool isTraceEq = (os1.str() == os2.str());
yulAssert(isTraceEq, "Interpreted traces for optimized and unoptimized code differ.");