mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8172 from ethereum/fix-7803
yul proto fuzzer: Do not generate infinite for loops and limit number of for loops
This commit is contained in:
commit
18bf3688be
@ -35,9 +35,18 @@ using namespace solidity;
|
|||||||
|
|
||||||
string ProtoConverter::dictionaryToken(HexPrefix _p)
|
string ProtoConverter::dictionaryToken(HexPrefix _p)
|
||||||
{
|
{
|
||||||
unsigned indexVar = m_inputSize * m_inputSize + counter();
|
std::string token;
|
||||||
std::string token = hexDictionary[indexVar % hexDictionary.size()];
|
// If dictionary constant is requested while converting
|
||||||
yulAssert(token.size() <= 64, "Proto Fuzzer: Dictionary token too large");
|
// for loop condition, then return zero so that we don't
|
||||||
|
// generate infinite for loops.
|
||||||
|
if (m_inForCond)
|
||||||
|
token = "0";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned indexVar = m_inputSize * m_inputSize + counter();
|
||||||
|
token = hexDictionary[indexVar % hexDictionary.size()];
|
||||||
|
yulAssert(token.size() <= 64, "Proto Fuzzer: Dictionary token too large");
|
||||||
|
}
|
||||||
|
|
||||||
return _p == HexPrefix::Add ? "0x" + token : token;
|
return _p == HexPrefix::Add ? "0x" + token : token;
|
||||||
}
|
}
|
||||||
@ -173,7 +182,13 @@ void ProtoConverter::visit(Expression const& _x)
|
|||||||
visit(_x.varref());
|
visit(_x.varref());
|
||||||
break;
|
break;
|
||||||
case Expression::kCons:
|
case Expression::kCons:
|
||||||
m_output << visit(_x.cons());
|
// If literal expression describes for-loop condition
|
||||||
|
// then force it to zero, so we don't generate infinite
|
||||||
|
// for loops
|
||||||
|
if (m_inForCond)
|
||||||
|
m_output << "0";
|
||||||
|
else
|
||||||
|
m_output << visit(_x.cons());
|
||||||
break;
|
break;
|
||||||
case Expression::kBinop:
|
case Expression::kBinop:
|
||||||
visit(_x.binop());
|
visit(_x.binop());
|
||||||
@ -964,17 +979,22 @@ void ProtoConverter::visit(StoreFunc const& _x)
|
|||||||
|
|
||||||
void ProtoConverter::visit(ForStmt const& _x)
|
void ProtoConverter::visit(ForStmt const& _x)
|
||||||
{
|
{
|
||||||
|
if (++m_numForLoops > s_maxForLoops)
|
||||||
|
return;
|
||||||
bool wasInForBody = m_inForBodyScope;
|
bool wasInForBody = m_inForBodyScope;
|
||||||
bool wasInForInit = m_inForInitScope;
|
bool wasInForInit = m_inForInitScope;
|
||||||
bool wasForInitScopeExtEnabled = m_forInitScopeExtEnabled;
|
bool wasForInitScopeExtEnabled = m_forInitScopeExtEnabled;
|
||||||
m_inForBodyScope = false;
|
m_inForBodyScope = false;
|
||||||
m_inForInitScope = true;
|
m_inForInitScope = true;
|
||||||
m_forInitScopeExtEnabled = true;
|
m_forInitScopeExtEnabled = true;
|
||||||
|
m_inForCond = false;
|
||||||
m_output << "for ";
|
m_output << "for ";
|
||||||
visit(_x.for_init());
|
visit(_x.for_init());
|
||||||
m_inForInitScope = false;
|
m_inForInitScope = false;
|
||||||
m_forInitScopeExtEnabled = wasForInitScopeExtEnabled;
|
m_forInitScopeExtEnabled = wasForInitScopeExtEnabled;
|
||||||
|
m_inForCond = true;
|
||||||
visit(_x.for_cond());
|
visit(_x.for_cond());
|
||||||
|
m_inForCond = false;
|
||||||
visit(_x.for_post());
|
visit(_x.for_post());
|
||||||
m_inForBodyScope = true;
|
m_inForBodyScope = true;
|
||||||
visit(_x.for_body());
|
visit(_x.for_body());
|
||||||
@ -997,6 +1017,9 @@ void ProtoConverter::visit(ForStmt const& _x)
|
|||||||
|
|
||||||
void ProtoConverter::visit(BoundedForStmt const& _x)
|
void ProtoConverter::visit(BoundedForStmt const& _x)
|
||||||
{
|
{
|
||||||
|
if (++m_numForLoops > s_maxForLoops)
|
||||||
|
return;
|
||||||
|
|
||||||
// Boilerplate for loop that limits the number of iterations to a maximum of 4.
|
// Boilerplate for loop that limits the number of iterations to a maximum of 4.
|
||||||
std::string loopVarName("i_" + std::to_string(m_numNestedForLoops++));
|
std::string loopVarName("i_" + std::to_string(m_numNestedForLoops++));
|
||||||
m_output << "for { let " << loopVarName << " := 0 } "
|
m_output << "for { let " << loopVarName << " := 0 } "
|
||||||
|
@ -42,7 +42,9 @@ public:
|
|||||||
m_globalVars = std::vector<std::vector<std::string>>{};
|
m_globalVars = std::vector<std::vector<std::string>>{};
|
||||||
m_inForBodyScope = false;
|
m_inForBodyScope = false;
|
||||||
m_inForInitScope = false;
|
m_inForInitScope = false;
|
||||||
|
m_inForCond = false;
|
||||||
m_numNestedForLoops = 0;
|
m_numNestedForLoops = 0;
|
||||||
|
m_numForLoops = 0;
|
||||||
m_counter = 0;
|
m_counter = 0;
|
||||||
m_inputSize = 0;
|
m_inputSize = 0;
|
||||||
m_inFunctionDef = false;
|
m_inFunctionDef = false;
|
||||||
@ -339,11 +341,18 @@ private:
|
|||||||
/// Predicate to keep track of for body scope. If false, break/continue
|
/// Predicate to keep track of for body scope. If false, break/continue
|
||||||
/// statements can not be created.
|
/// statements can not be created.
|
||||||
bool m_inForBodyScope;
|
bool m_inForBodyScope;
|
||||||
|
/// Maximum number of for loops that a test case may contain
|
||||||
|
static auto constexpr s_maxForLoops = 2;
|
||||||
// Index used for naming loop variable of bounded for loops
|
// Index used for naming loop variable of bounded for loops
|
||||||
unsigned m_numNestedForLoops;
|
unsigned m_numNestedForLoops;
|
||||||
|
/// Counter for number of for loops
|
||||||
|
unsigned m_numForLoops;
|
||||||
/// Predicate to keep track of for loop init scope. If true, variable
|
/// Predicate to keep track of for loop init scope. If true, variable
|
||||||
/// or function declarations can not be created.
|
/// or function declarations can not be created.
|
||||||
bool m_inForInitScope;
|
bool m_inForInitScope;
|
||||||
|
/// Flag that is true while converting for loop condition,
|
||||||
|
/// false otherwise.
|
||||||
|
bool m_inForCond;
|
||||||
/// Monotonically increasing counter
|
/// Monotonically increasing counter
|
||||||
unsigned m_counter;
|
unsigned m_counter;
|
||||||
/// Size of protobuf input
|
/// Size of protobuf input
|
||||||
|
Loading…
Reference in New Issue
Block a user