Yul fuzzer: Enable nested object references

Co-authored-by: Đorđe Mijović <djordje.mijovic@gmail.com>
This commit is contained in:
Bhargava Shastry 2020-07-22 12:24:11 +02:00
parent 4a478f0fb2
commit 115380ca76
3 changed files with 24 additions and 18 deletions

View File

@ -1848,8 +1848,12 @@ void ProtoConverter::visit(LeaveStmt const&)
string ProtoConverter::getObjectIdentifier(unsigned _x) string ProtoConverter::getObjectIdentifier(unsigned _x)
{ {
unsigned currentId = currentObjectId(); unsigned currentId = currentObjectId();
yulAssert(m_objectScopeTree.size() > currentId, "Proto fuzzer: Error referencing object"); string currentObjName = "object" + to_string(currentId);
std::vector<std::string> objectIdsInScope = m_objectScopeTree[currentId]; yulAssert(
m_objectScope.count(currentObjName) && m_objectScope.at(currentObjName).size() > 0,
"Yul proto fuzzer: Error referencing object"
);
vector<string> objectIdsInScope = m_objectScope.at(currentObjName);
return objectIdsInScope[_x % objectIdsInScope.size()]; return objectIdsInScope[_x % objectIdsInScope.size()];
} }
@ -1875,31 +1879,33 @@ void ProtoConverter::visit(Object const& _x)
visit(_x.code()); visit(_x.code());
if (_x.has_data()) if (_x.has_data())
visit(_x.data()); visit(_x.data());
if (_x.has_sub_obj()) for (auto const& subObj: _x.sub_obj())
visit(_x.sub_obj()); visit(subObj);
m_output << "}\n"; m_output << "}\n";
} }
void ProtoConverter::buildObjectScopeTree(Object const& _x) void ProtoConverter::buildObjectScopeTree(Object const& _x)
{ {
// Identifies object being visited // Identifies object being visited
string objectId = newObjectId(false); string objectName = newObjectId(false);
vector<string> node{objectId}; vector<string> node{objectName};
if (_x.has_data()) if (_x.has_data())
node.push_back(s_dataIdentifier); node.push_back(s_dataIdentifier);
if (_x.has_sub_obj()) for (auto const& subObj: _x.sub_obj())
{ {
// Identifies sub object whose numeric suffix is // Identifies sub object whose numeric suffix is
// m_objectId // m_objectId
string subObjectId = "object" + to_string(m_objectId); unsigned subObjectId = m_objectId;
node.push_back(subObjectId); string subObjectName = "object" + to_string(subObjectId);
// TODO: Add sub-object to object's ancestors once node.push_back(subObjectName);
// nested access is implemented. buildObjectScopeTree(subObj);
m_objectScopeTree.push_back(node); // Add sub-object to object's ancestors
buildObjectScopeTree(_x.sub_obj()); yulAssert(m_objectScope.count(subObjectName), "Yul proto fuzzer: Invalid object hierarchy");
for (string const& item: m_objectScope.at(subObjectName))
if (item != subObjectName)
node.push_back(subObjectName + "." + item);
} }
else m_objectScope.emplace(objectName, node);
m_objectScopeTree.push_back(node);
} }
void ProtoConverter::visit(Program const& _x) void ProtoConverter::visit(Program const& _x)

View File

@ -352,8 +352,8 @@ private:
std::stack<std::set<u256>> m_switchLiteralSetPerScope; std::stack<std::set<u256>> m_switchLiteralSetPerScope;
// Look-up table per function type that holds the number of input (output) function parameters // Look-up table per function type that holds the number of input (output) function parameters
std::map<std::string, std::pair<unsigned, unsigned>> m_functionSigMap; std::map<std::string, std::pair<unsigned, unsigned>> m_functionSigMap;
/// Tree of objects and their scopes /// Map of object name to list of sub-object namespace(s) in scope
std::vector<std::vector<std::string>> m_objectScopeTree; std::map<std::string, std::vector<std::string>> m_objectScope;
// mod input/output parameters impose an upper bound on the number of input/output parameters a function may have. // mod input/output parameters impose an upper bound on the number of input/output parameters a function may have.
static unsigned constexpr s_modInputParams = 5; static unsigned constexpr s_modInputParams = 5;
static unsigned constexpr s_modOutputParams = 5; static unsigned constexpr s_modOutputParams = 5;

View File

@ -389,7 +389,7 @@ message Block {
message Object { message Object {
required Code code = 1; required Code code = 1;
optional Data data = 2; optional Data data = 2;
optional Object sub_obj = 3; repeated Object sub_obj = 3;
} }
message Code { message Code {