Merge pull request #9459 from ethereum/fix-9458

Fuzzer: Count step by number of interpreted statements
This commit is contained in:
chriseth 2020-07-21 18:05:31 +02:00 committed by GitHub
commit 47ab6e73a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 11 deletions

View File

@ -99,7 +99,7 @@ string EwasmTranslationTest::interpret()
{ {
InterpreterState state; InterpreterState state;
state.maxTraceSize = 10000; state.maxTraceSize = 10000;
state.maxSteps = 100000; state.maxSteps = 1000000;
try try
{ {
Interpreter::run(state, WasmDialect{}, *m_object->code); Interpreter::run(state, WasmDialect{}, *m_object->code);

View File

@ -97,15 +97,17 @@ DEFINE_PROTO_FUZZER(Program const& _input)
EVMDialect::strictAssemblyForEVMObjects(version) EVMDialect::strictAssemblyForEVMObjects(version)
); );
if (termReason == yulFuzzerUtil::TerminationReason::StepLimitReached) if (
termReason == yulFuzzerUtil::TerminationReason::StepLimitReached ||
termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached
)
return; return;
stack.optimize(); stack.optimize();
termReason = yulFuzzerUtil::interpret( yulFuzzerUtil::interpret(
os2, os2,
stack.parserResult()->code, stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(version), EVMDialect::strictAssemblyForEVMObjects(version)
(yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 4)
); );
bool isTraceEq = (os1.str() == os2.str()); bool isTraceEq = (os1.str() == os2.str());

View File

@ -145,6 +145,11 @@ void Interpreter::operator()(ForLoop const& _forLoop)
} }
while (evaluate(*_forLoop.condition) != 0) while (evaluate(*_forLoop.condition) != 0)
{ {
// Increment step for each loop iteration for loops with
// an empty body and post blocks to prevent a deadlock.
if (_forLoop.body.statements.size() == 0 && _forLoop.post.statements.size() == 0)
incrementStep();
m_state.controlFlowState = ControlFlowState::Default; m_state.controlFlowState = ControlFlowState::Default;
(*this)(_forLoop.body); (*this)(_forLoop.body);
if (m_state.controlFlowState == ControlFlowState::Break || m_state.controlFlowState == ControlFlowState::Leave) if (m_state.controlFlowState == ControlFlowState::Break || m_state.controlFlowState == ControlFlowState::Leave)
@ -176,12 +181,6 @@ void Interpreter::operator()(Leave const&)
void Interpreter::operator()(Block const& _block) void Interpreter::operator()(Block const& _block)
{ {
m_state.numSteps++;
if (m_state.maxSteps > 0 && m_state.numSteps >= m_state.maxSteps)
{
m_state.trace.emplace_back("Interpreter execution step limit reached.");
throw StepLimitReached();
}
enterScope(_block); enterScope(_block);
// Register functions. // Register functions.
for (auto const& statement: _block.statements) for (auto const& statement: _block.statements)
@ -193,6 +192,7 @@ void Interpreter::operator()(Block const& _block)
for (auto const& statement: _block.statements) for (auto const& statement: _block.statements)
{ {
incrementStep();
visit(statement); visit(statement);
if (m_state.controlFlowState != ControlFlowState::Default) if (m_state.controlFlowState != ControlFlowState::Default)
break; break;
@ -235,6 +235,16 @@ void Interpreter::leaveScope()
yulAssert(m_scope, ""); yulAssert(m_scope, "");
} }
void Interpreter::incrementStep()
{
m_state.numSteps++;
if (m_state.maxSteps > 0 && m_state.numSteps >= m_state.maxSteps)
{
m_state.trace.emplace_back("Interpreter execution step limit reached.");
throw StepLimitReached();
}
}
void ExpressionEvaluator::operator()(Literal const& _literal) void ExpressionEvaluator::operator()(Literal const& _literal)
{ {
static YulString const trueString("true"); static YulString const trueString("true");

View File

@ -154,6 +154,10 @@ private:
void enterScope(Block const& _block); void enterScope(Block const& _block);
void leaveScope(); void leaveScope();
/// Increment interpreter step count, throwing exception if step limit
/// is reached.
void incrementStep();
Dialect const& m_dialect; Dialect const& m_dialect;
InterpreterState& m_state; InterpreterState& m_state;
/// Values of variables. /// Values of variables.