Add custom mutation to increase stack pressure.

This commit is contained in:
Bhargava Shastry 2021-04-13 19:34:36 +02:00
parent 39a0ecd589
commit c9a0ccde3d
3 changed files with 37 additions and 14 deletions

View File

@ -108,6 +108,7 @@ DEFINE_PROTO_FUZZER(Program const& _input)
solidity::frontend::OptimiserSettings settings = solidity::frontend::OptimiserSettings::none();
// Stack evader requires stack allocation to be done.
settings.optimizeStackAllocation = true;
settings.runYulOptimiser = true;
AssemblyStack stackUnoptimized(version, AssemblyStack::Language::StrictAssembly, settings);
solAssert(
stackUnoptimized.parseAndAnalyze("source", yulSubObject),
@ -156,6 +157,7 @@ DEFINE_PROTO_FUZZER(Program const& _input)
.render();
cout << AsmPrinter{}(*astBlock) << endl;
bytes optimisedByteCode;
settings.runYulOptimiser = false;
optimisedByteCode = YulAssembler{version, settings, optimisedProgram}.assemble();
// Reset host before running optimised code.
@ -185,6 +187,8 @@ DEFINE_PROTO_FUZZER(Program const& _input)
(!noInvalidInSource && callResultOpt.status_code == EVMC_INVALID_INSTRUCTION)),
"Optimised call failed."
);
if (callResultOpt.status_code == EVMC_OUT_OF_GAS)
return;
ostringstream optimizedState;
optimizedState << EVMHostPrinter{hostContext, deployResultOpt.create_address}.storageOnly();

View File

@ -216,7 +216,11 @@ void ProtoConverter::visit(Expression const& _x)
if (auto v = functionExists(NumFunctionReturns::Single); v.has_value())
{
string functionName = v.value();
visit(_x.func_expr(), functionName, true);
// Disable recursive calls.
if (functionName == m_currentFunctionName)
m_output << dictionaryToken();
else
visit(_x.func_expr(), functionName, true);
}
else
m_output << dictionaryToken();
@ -1053,9 +1057,6 @@ optional<string> ProtoConverter::functionExists(NumFunctionReturns _numReturns)
void ProtoConverter::visit(FunctionCall const& _x, string const& _functionName, bool _expression)
{
// Disable recursive calls.
if (_functionName == m_currentFunctionName)
return;
yulAssert(m_functionSigMap.count(_functionName), "Proto fuzzer: Invalid function.");
auto ret = m_functionSigMap.at(_functionName);
unsigned numInParams = ret.first;
@ -1350,7 +1351,8 @@ void ProtoConverter::visit(TerminatingStmt const& _x)
visit(_x.stop_invalid());
break;
case TerminatingStmt::kRetRev:
visit(_x.ret_rev());
if (!m_filterStatefulInstructions)
visit(_x.ret_rev());
break;
case TerminatingStmt::kSelfDes:
if (!m_filterStatefulInstructions)
@ -1444,7 +1446,8 @@ void ProtoConverter::visit(Statement const& _x)
unsigned index = counter() % m_functionSigMap.size();
auto iter = m_functionSigMap.begin();
advance(iter, index);
visit(_x.functioncall(), iter->first);
if (iter->first != m_currentFunctionName)
visit(_x.functioncall(), iter->first);
}
break;
case Statement::kFuncdef:
@ -1738,16 +1741,10 @@ void ProtoConverter::saveFunctionCallOutput(vector<string> const& _varsVec)
{
for (auto const& var: _varsVec)
{
// Flip a dice to choose whether to save output values
// in storage or memory.
bool coinFlip = counter() % 2 == 0;
// Pseudo-randomly choose one of the first ten 32-byte
// aligned slots.
string slot = to_string((counter() % 10) * 32);
if (coinFlip)
m_output << "sstore(" << slot << ", " << var << ")\n";
else
m_output << "mstore(" << slot << ", " << var << ")\n";
m_output << "sstore(" << slot << ", " << var << ")\n";
}
}
@ -1895,7 +1892,7 @@ void ProtoConverter::visit(Code const& _x)
m_output << "}\n";
}
void ProtoConverter::visit(Data const& _x)
void ProtoConverter::visit(Data const&)
{
// TODO: Generate random data block identifier
m_output << "data \"" << s_dataIdentifier << "\" hex\"" << "deadbeef" << "\"\n";

View File

@ -46,6 +46,28 @@ static LPMPostProcessor<Block> addStoreToZero(
}
);
static LPMPostProcessor<FunctionDef> addStackPressure(
[](FunctionDef* _message, unsigned _seed)
{
{
MutationInfo m{_message, "Added stack pressure"};
auto functionBlock = _message->mutable_block();
int numInputParams = _message->num_input_params() % 33;
int numOutputParams = _message->num_output_params() % 33;
if (numOutputParams > 0)
{
for (int i = 0; i < numOutputParams; i++)
{
auto varRef = new VarRef();
varRef->set_varnum(numInputParams + i);
auto assignOutI = new AssignmentStatement();
assignOutI->set_allocated_ref_id(varRef);
functionBlock->add_statements()->set_allocated_assignment(assignOutI);
}
}
}
}
);
namespace
{