mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Yul interpreter: Limit nesting level
This commit is contained in:
parent
0b1d0e0bd2
commit
fcef97043a
@ -100,6 +100,7 @@ string EwasmTranslationTest::interpret()
|
||||
InterpreterState state;
|
||||
state.maxTraceSize = 10000;
|
||||
state.maxSteps = 1000000;
|
||||
state.maxExprNesting = 60;
|
||||
try
|
||||
{
|
||||
Interpreter::run(state, WasmDialect{}, *m_object->code);
|
||||
|
@ -89,6 +89,7 @@ string YulInterpreterTest::interpret()
|
||||
InterpreterState state;
|
||||
state.maxTraceSize = 10;
|
||||
state.maxSteps = 150;
|
||||
state.maxExprNesting = 60;
|
||||
try
|
||||
{
|
||||
Interpreter::run(state, EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}), *m_ast);
|
||||
|
@ -27,12 +27,14 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret(
|
||||
shared_ptr<yul::Block> _ast,
|
||||
Dialect const& _dialect,
|
||||
size_t _maxSteps,
|
||||
size_t _maxTraceSize
|
||||
size_t _maxTraceSize,
|
||||
size_t _maxExprNesting
|
||||
)
|
||||
{
|
||||
InterpreterState state;
|
||||
state.maxTraceSize = _maxTraceSize;
|
||||
state.maxSteps = _maxSteps;
|
||||
state.maxExprNesting = _maxExprNesting;
|
||||
// Add 64 bytes of pseudo-randomly generated calldata so that
|
||||
// calldata opcodes perform non trivial work.
|
||||
state.calldata = {
|
||||
@ -59,6 +61,10 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret(
|
||||
{
|
||||
reason = TerminationReason::TraceLimitReached;
|
||||
}
|
||||
catch (ExpressionNestingLimitReached const&)
|
||||
{
|
||||
reason = TerminationReason::ExpresionNestingLimitReached;
|
||||
}
|
||||
catch (ExplicitlyTerminated const&)
|
||||
{
|
||||
reason = TerminationReason::ExplicitlyTerminated;
|
||||
|
@ -28,6 +28,7 @@ struct yulFuzzerUtil
|
||||
ExplicitlyTerminated,
|
||||
StepLimitReached,
|
||||
TraceLimitReached,
|
||||
ExpresionNestingLimitReached,
|
||||
None
|
||||
};
|
||||
|
||||
@ -36,10 +37,12 @@ struct yulFuzzerUtil
|
||||
std::shared_ptr<yul::Block> _ast,
|
||||
Dialect const& _dialect,
|
||||
size_t _maxSteps = maxSteps,
|
||||
size_t _maxTraceSize = maxTraceSize
|
||||
size_t _maxTraceSize = maxTraceSize,
|
||||
size_t _maxExprNesting = maxExprNesting
|
||||
);
|
||||
static size_t constexpr maxSteps = 100;
|
||||
static size_t constexpr maxTraceSize = 75;
|
||||
static size_t constexpr maxExprNesting = 60;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -91,19 +91,25 @@ DEFINE_PROTO_FUZZER(Program const& _input)
|
||||
|
||||
ostringstream os1;
|
||||
ostringstream os2;
|
||||
yulFuzzerUtil::interpret(
|
||||
yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret(
|
||||
os1,
|
||||
stack.parserResult()->code,
|
||||
EVMDialect::strictAssemblyForEVMObjects(version)
|
||||
);
|
||||
|
||||
if (
|
||||
termReason == yulFuzzerUtil::TerminationReason::StepLimitReached ||
|
||||
termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached ||
|
||||
termReason == yulFuzzerUtil::TerminationReason::ExpresionNestingLimitReached
|
||||
)
|
||||
return;
|
||||
|
||||
stack.optimize();
|
||||
yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret(
|
||||
termReason = yulFuzzerUtil::interpret(
|
||||
os2,
|
||||
stack.parserResult()->code,
|
||||
EVMDialect::strictAssemblyForEVMObjects(version)
|
||||
);
|
||||
|
||||
if (termReason == yulFuzzerUtil::TerminationReason::StepLimitReached)
|
||||
return;
|
||||
|
||||
|
@ -247,6 +247,7 @@ void Interpreter::incrementStep()
|
||||
|
||||
void ExpressionEvaluator::operator()(Literal const& _literal)
|
||||
{
|
||||
incrementStep();
|
||||
static YulString const trueString("true");
|
||||
static YulString const falseString("false");
|
||||
|
||||
@ -256,6 +257,7 @@ void ExpressionEvaluator::operator()(Literal const& _literal)
|
||||
void ExpressionEvaluator::operator()(Identifier const& _identifier)
|
||||
{
|
||||
solAssert(m_variables.count(_identifier.name), "");
|
||||
incrementStep();
|
||||
setValue(m_variables.at(_identifier.name));
|
||||
}
|
||||
|
||||
@ -319,6 +321,7 @@ void ExpressionEvaluator::setValue(u256 _value)
|
||||
|
||||
void ExpressionEvaluator::evaluateArgs(vector<Expression> const& _expr)
|
||||
{
|
||||
incrementStep();
|
||||
vector<u256> values;
|
||||
/// Function arguments are evaluated in reverse.
|
||||
for (auto const& expr: _expr | boost::adaptors::reversed)
|
||||
@ -329,3 +332,13 @@ void ExpressionEvaluator::evaluateArgs(vector<Expression> const& _expr)
|
||||
m_values = std::move(values);
|
||||
std::reverse(m_values.begin(), m_values.end());
|
||||
}
|
||||
|
||||
void ExpressionEvaluator::incrementStep()
|
||||
{
|
||||
m_nestingLevel++;
|
||||
if (m_state.maxExprNesting > 0 && m_nestingLevel > m_state.maxExprNesting)
|
||||
{
|
||||
m_state.trace.emplace_back("Maximum expression nesting level reached.");
|
||||
throw ExpressionNestingLimitReached();
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,10 @@ class TraceLimitReached: public InterpreterTerminatedGeneric
|
||||
{
|
||||
};
|
||||
|
||||
class ExpressionNestingLimitReached: public InterpreterTerminatedGeneric
|
||||
{
|
||||
};
|
||||
|
||||
enum class ControlFlowState
|
||||
{
|
||||
Default,
|
||||
@ -92,6 +96,7 @@ struct InterpreterState
|
||||
size_t maxTraceSize = 0;
|
||||
size_t maxSteps = 0;
|
||||
size_t numSteps = 0;
|
||||
size_t maxExprNesting = 0;
|
||||
ControlFlowState controlFlowState = ControlFlowState::Default;
|
||||
|
||||
void dumpTraceAndState(std::ostream& _out) const;
|
||||
@ -199,6 +204,11 @@ private:
|
||||
/// stores it in m_value.
|
||||
void evaluateArgs(std::vector<Expression> const& _expr);
|
||||
|
||||
/// Increment evaluation count, throwing exception if the
|
||||
/// nesting level is beyond the upper bound configured in
|
||||
/// the interpreter state.
|
||||
void incrementStep();
|
||||
|
||||
InterpreterState& m_state;
|
||||
Dialect const& m_dialect;
|
||||
/// Values of variables.
|
||||
@ -206,6 +216,8 @@ private:
|
||||
Scope& m_scope;
|
||||
/// Current value of the expression
|
||||
std::vector<u256> m_values;
|
||||
/// Current expression nesting level
|
||||
unsigned m_nestingLevel = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user