Disable more than one reference to a variable on the LHS of a tuple assignment

This commit is contained in:
Bhargava Shastry 2020-07-06 14:09:06 +02:00
parent 89231bea1e
commit 48ac4b2954
2 changed files with 43 additions and 13 deletions

View File

@ -178,6 +178,14 @@ bool ProtoConverter::functionCallNotPossible(FunctionCall_Returns _type)
(_type == FunctionCall::MULTIASSIGN && !varDeclAvailable()); (_type == FunctionCall::MULTIASSIGN && !varDeclAvailable());
} }
unsigned ProtoConverter::numVarsInScope()
{
if (m_inFunctionDef)
return m_currentFuncVars.size();
else
return m_currentGlobalVars.size();
}
void ProtoConverter::visit(VarRef const& _x) void ProtoConverter::visit(VarRef const& _x)
{ {
if (m_inFunctionDef) if (m_inFunctionDef)
@ -830,18 +838,18 @@ void ProtoConverter::visitFunctionInputParams(FunctionCall const& _x, unsigned _
case 4: case 4:
visit(_x.in_param4()); visit(_x.in_param4());
m_output << ", "; m_output << ", ";
BOOST_FALLTHROUGH; [[fallthrough]];
case 3: case 3:
visit(_x.in_param3()); visit(_x.in_param3());
m_output << ", "; m_output << ", ";
BOOST_FALLTHROUGH; [[fallthrough]];
case 2: case 2:
visit(_x.in_param2()); visit(_x.in_param2());
m_output << ", "; m_output << ", ";
BOOST_FALLTHROUGH; [[fallthrough]];
case 1: case 1:
visit(_x.in_param1()); visit(_x.in_param1());
BOOST_FALLTHROUGH; [[fallthrough]];
case 0: case 0:
break; break;
default: default:
@ -966,23 +974,43 @@ void ProtoConverter::visit(FunctionCall const& _x)
"Proto fuzzer: Function call with too many output params encountered." "Proto fuzzer: Function call with too many output params encountered."
); );
// Return early if numOutParams > number of available variables
if (numOutParams > numVarsInScope())
return;
// Copy variables in scope in order to prevent repeated references
vector<string> variables;
if (m_inFunctionDef)
for (auto var: m_currentFuncVars)
variables.push_back(*var);
else
for (auto var: m_currentGlobalVars)
variables.push_back(*var);
auto refVar = [](vector<string>& _var, unsigned _rand, bool _comma = true) -> string
{
auto index = _rand % _var.size();
string ref = _var[index];
_var.erase(_var.begin() + index);
if (_comma)
ref += ", ";
return ref;
};
// Convert LHS of multi assignment // Convert LHS of multi assignment
// We reverse the order of out param visits since the order does not matter. // We reverse the order of out param visits since the order does not matter.
// This helps reduce the size of this switch statement. // This helps reduce the size of this switch statement.
switch (numOutParams) switch (numOutParams)
{ {
case 4: case 4:
visit(_x.out_param4()); m_output << refVar(variables, _x.out_param4().varnum());
m_output << ", "; [[fallthrough]];
BOOST_FALLTHROUGH;
case 3: case 3:
visit(_x.out_param3()); m_output << refVar(variables, _x.out_param3().varnum());
m_output << ", "; [[fallthrough]];
BOOST_FALLTHROUGH;
case 2: case 2:
visit(_x.out_param2()); m_output << refVar(variables, _x.out_param2().varnum());
m_output << ", "; m_output << refVar(variables, _x.out_param1().varnum(), false);
visit(_x.out_param1());
break; break;
default: default:
yulAssert(false, "Proto fuzzer: Function call with too many or too few input parameters."); yulAssert(false, "Proto fuzzer: Function call with too many or too few input parameters.");

View File

@ -120,6 +120,8 @@ private:
void closeFunctionScope(); void closeFunctionScope();
/// Adds @a _vars to current scope /// Adds @a _vars to current scope
void addVarsToScope(std::vector<std::string> const& _vars); void addVarsToScope(std::vector<std::string> const& _vars);
/// @returns number of variables that are in scope
unsigned numVarsInScope();
std::string createHex(std::string const& _hexBytes); std::string createHex(std::string const& _hexBytes);