diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 1d78dc802..6c229c164 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -1848,8 +1848,12 @@ void ProtoConverter::visit(LeaveStmt const&) string ProtoConverter::getObjectIdentifier(unsigned _x) { unsigned currentId = currentObjectId(); - yulAssert(m_objectScopeTree.size() > currentId, "Proto fuzzer: Error referencing object"); - std::vector objectIdsInScope = m_objectScopeTree[currentId]; + string currentObjName = "object" + to_string(currentId); + yulAssert( + m_objectScope.count(currentObjName) && m_objectScope.at(currentObjName).size() > 0, + "Yul proto fuzzer: Error referencing object" + ); + vector objectIdsInScope = m_objectScope.at(currentObjName); return objectIdsInScope[_x % objectIdsInScope.size()]; } @@ -1875,31 +1879,33 @@ void ProtoConverter::visit(Object const& _x) visit(_x.code()); if (_x.has_data()) visit(_x.data()); - if (_x.has_sub_obj()) - visit(_x.sub_obj()); + for (auto const& subObj: _x.sub_obj()) + visit(subObj); m_output << "}\n"; } void ProtoConverter::buildObjectScopeTree(Object const& _x) { // Identifies object being visited - string objectId = newObjectId(false); - vector node{objectId}; + string objectName = newObjectId(false); + vector node{objectName}; if (_x.has_data()) node.push_back(s_dataIdentifier); - if (_x.has_sub_obj()) + for (auto const& subObj: _x.sub_obj()) { // Identifies sub object whose numeric suffix is // m_objectId - string subObjectId = "object" + to_string(m_objectId); - node.push_back(subObjectId); - // TODO: Add sub-object to object's ancestors once - // nested access is implemented. - m_objectScopeTree.push_back(node); - buildObjectScopeTree(_x.sub_obj()); + unsigned subObjectId = m_objectId; + string subObjectName = "object" + to_string(subObjectId); + node.push_back(subObjectName); + buildObjectScopeTree(subObj); + // Add sub-object to object's ancestors + 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_objectScopeTree.push_back(node); + m_objectScope.emplace(objectName, node); } void ProtoConverter::visit(Program const& _x) diff --git a/test/tools/ossfuzz/protoToYul.h b/test/tools/ossfuzz/protoToYul.h index 9b8de1480..bf9963726 100644 --- a/test/tools/ossfuzz/protoToYul.h +++ b/test/tools/ossfuzz/protoToYul.h @@ -352,8 +352,8 @@ private: std::stack> m_switchLiteralSetPerScope; // Look-up table per function type that holds the number of input (output) function parameters std::map> m_functionSigMap; - /// Tree of objects and their scopes - std::vector> m_objectScopeTree; + /// Map of object name to list of sub-object namespace(s) in scope + std::map> m_objectScope; // 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_modOutputParams = 5; diff --git a/test/tools/ossfuzz/yulProto.proto b/test/tools/ossfuzz/yulProto.proto index d87d067f2..7146b9a49 100644 --- a/test/tools/ossfuzz/yulProto.proto +++ b/test/tools/ossfuzz/yulProto.proto @@ -389,7 +389,7 @@ message Block { message Object { required Code code = 1; optional Data data = 2; - optional Object sub_obj = 3; + repeated Object sub_obj = 3; } message Code {