mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add custom mutation to increase stack pressure.
This commit is contained in:
parent
39a0ecd589
commit
c9a0ccde3d
@ -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();
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user