From a3d84f029362995d6ad5aed59842753094097541 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Mon, 11 Nov 2019 13:57:21 +0100 Subject: [PATCH] yul proto fuzzer: Limit number of nested for loops --- test/tools/ossfuzz/protoToYul.cpp | 20 ++++++++++++++++++++ test/tools/ossfuzz/protoToYul.h | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 8da031620..224030178 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -856,23 +856,40 @@ void ProtoConverter::visit(StoreFunc const& _x) void ProtoConverter::visit(ForStmt const& _x) { + if (m_numNestedForLoops + 1 > s_maxNestedForLoops) + return; + + if (m_inForBodyScope || m_inForPostScope || m_numNestedForLoops == 0) + m_numNestedForLoops++; + bool wasInForBody = m_inForBodyScope; bool wasInForInit = m_inForInitScope; + bool wasInForPost = m_inForPostScope; m_inForBodyScope = false; + m_inForPostScope = false; m_inForInitScope = true; m_output << "for "; visit(_x.for_init()); m_inForInitScope = false; visit(_x.for_cond()); + m_inForPostScope = true; visit(_x.for_post()); + m_inForPostScope = false; m_inForBodyScope = true; visit(_x.for_body()); m_inForBodyScope = wasInForBody; m_inForInitScope = wasInForInit; + m_inForPostScope = wasInForPost; } void ProtoConverter::visit(BoundedForStmt const& _x) { + if (m_numNestedForLoops + 1 > s_maxNestedForLoops) + return; + + if (m_inForBodyScope || m_inForPostScope || m_numNestedForLoops == 0) + m_numNestedForLoops++; + // Boilerplate for loop that limits the number of iterations to a maximum of 4. std::string loopVarName("i_" + std::to_string(m_numNestedForLoops++)); m_output << "for { let " << loopVarName << " := 0 } " @@ -881,12 +898,15 @@ void ProtoConverter::visit(BoundedForStmt const& _x) // Store previous for body scope bool wasInForBody = m_inForBodyScope; bool wasInForInit = m_inForInitScope; + bool wasInForPost = m_inForPostScope; m_inForBodyScope = true; m_inForInitScope = false; + m_inForPostScope = false; visit(_x.for_body()); // Restore previous for body scope and init m_inForBodyScope = wasInForBody; m_inForInitScope = wasInForInit; + m_inForPostScope = wasInForPost; } void ProtoConverter::visit(CaseStmt const& _x) diff --git a/test/tools/ossfuzz/protoToYul.h b/test/tools/ossfuzz/protoToYul.h index 2d5d8a10a..19c9705e3 100644 --- a/test/tools/ossfuzz/protoToYul.h +++ b/test/tools/ossfuzz/protoToYul.h @@ -46,6 +46,7 @@ public: m_variables = std::vector>{}; m_inForBodyScope = false; m_inForInitScope = false; + m_inForPostScope = false; m_numNestedForLoops = 0; m_numFunctionCalls = 0; m_counter = 0; @@ -337,6 +338,8 @@ private: static unsigned constexpr s_maxFunctionCalls = 3; /// Lower bound for function statement count to be considered non-trivial static unsigned constexpr s_minStatements = 5; + /// Upper bound for number of nested for loops + static unsigned constexpr s_maxNestedForLoops = 3; /// Hard-coded identifier for a Yul object's data block static auto constexpr s_dataIdentifier = "datablock"; /// Predicate to keep track of for body scope. If true, break/continue @@ -349,6 +352,8 @@ private: /// Predicate to keep track of for loop init scope. If true, variable /// or function declarations can not be created. bool m_inForInitScope; + /// Predicate to keep track of for loop post scope. + bool m_inForPostScope; /// Monotonically increasing counter unsigned m_counter; /// Size of protobuf input