From 18fbbfa5ca4e62e6d371123de215e065c15e16e2 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Tue, 21 Jul 2020 14:37:22 +0200 Subject: [PATCH] Fuzzer: Count step by number of interpreted statements Co-authored-by: chriseth --- test/libyul/EwasmTranslationTest.cpp | 2 +- test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp | 10 +++++---- test/tools/yulInterpreter/Interpreter.cpp | 22 ++++++++++++++------ test/tools/yulInterpreter/Interpreter.h | 4 ++++ 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/test/libyul/EwasmTranslationTest.cpp b/test/libyul/EwasmTranslationTest.cpp index dd732f9a8..be9ed77d9 100644 --- a/test/libyul/EwasmTranslationTest.cpp +++ b/test/libyul/EwasmTranslationTest.cpp @@ -99,7 +99,7 @@ string EwasmTranslationTest::interpret() { InterpreterState state; state.maxTraceSize = 10000; - state.maxSteps = 100000; + state.maxSteps = 1000000; try { Interpreter::run(state, WasmDialect{}, *m_object->code); diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index 4c8ddb94f..c95b4db7f 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -97,15 +97,17 @@ DEFINE_PROTO_FUZZER(Program const& _input) EVMDialect::strictAssemblyForEVMObjects(version) ); - if (termReason == yulFuzzerUtil::TerminationReason::StepLimitReached) + if ( + termReason == yulFuzzerUtil::TerminationReason::StepLimitReached || + termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached + ) return; stack.optimize(); - termReason = yulFuzzerUtil::interpret( + yulFuzzerUtil::interpret( os2, stack.parserResult()->code, - EVMDialect::strictAssemblyForEVMObjects(version), - (yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 4) + EVMDialect::strictAssemblyForEVMObjects(version) ); bool isTraceEq = (os1.str() == os2.str()); diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index ba946e732..a8496793f 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -145,6 +145,11 @@ void Interpreter::operator()(ForLoop const& _forLoop) } 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; (*this)(_forLoop.body); 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) { - 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); // Register functions. for (auto const& statement: _block.statements) @@ -193,6 +192,7 @@ void Interpreter::operator()(Block const& _block) for (auto const& statement: _block.statements) { + incrementStep(); visit(statement); if (m_state.controlFlowState != ControlFlowState::Default) break; @@ -235,6 +235,16 @@ void Interpreter::leaveScope() 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) { static YulString const trueString("true"); diff --git a/test/tools/yulInterpreter/Interpreter.h b/test/tools/yulInterpreter/Interpreter.h index a52c098ed..00e02f6e2 100644 --- a/test/tools/yulInterpreter/Interpreter.h +++ b/test/tools/yulInterpreter/Interpreter.h @@ -154,6 +154,10 @@ private: void enterScope(Block const& _block); void leaveScope(); + /// Increment interpreter step count, throwing exception if step limit + /// is reached. + void incrementStep(); + Dialect const& m_dialect; InterpreterState& m_state; /// Values of variables.