From b6b0a99afcbc66225610fa359e09b4b5c1172589 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Mon, 11 Nov 2019 11:35:16 +0100 Subject: [PATCH] yul proto fuzzer: Place an upper bound on number of function calls generated --- test/tools/ossfuzz/protoToYul.cpp | 21 +++++++++++++++++---- test/tools/ossfuzz/protoToYul.h | 9 ++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 34ab06982..8da031620 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -1410,14 +1410,27 @@ void ProtoConverter::createFunctionDefAndCall( !m_inForInitScope, "Proto fuzzer: Trying to create function call inside for-init block" ); - createFunctionCall(funcName, _numInParams, _numOutParams); + + // Create a function call pseudo randomly. The heuristic for this is + // - We have not exceeded the maximum function call limit + // - Function to be called qualifies as non trivial + // - A function is non trivial if it contains at least "s_minStatements" + // statements + if (m_numFunctionCalls < s_maxFunctionCalls) + if (static_cast(_x.block().statements_size()) >= s_minStatements) + { + createFunctionCall(funcName, _numInParams, _numOutParams); + m_numFunctionCalls++; + } } void ProtoConverter::visit(FunctionDef const& _x) { - unsigned numInParams = _x.num_input_params() % s_modInputParams; - unsigned numOutParams = _x.num_output_params() % s_modOutputParams; - createFunctionDefAndCall(_x, numInParams, numOutParams); + createFunctionDefAndCall( + _x, + _x.num_input_params() % s_modInputParams, + _x.num_output_params() % s_modOutputParams + ); } void ProtoConverter::visit(PopStmt const& _x) diff --git a/test/tools/ossfuzz/protoToYul.h b/test/tools/ossfuzz/protoToYul.h index 6823a2925..2d5d8a10a 100644 --- a/test/tools/ossfuzz/protoToYul.h +++ b/test/tools/ossfuzz/protoToYul.h @@ -47,6 +47,7 @@ public: m_inForBodyScope = false; m_inForInitScope = false; m_numNestedForLoops = 0; + m_numFunctionCalls = 0; m_counter = 0; m_inputSize = 0; m_inFunctionDef = false; @@ -329,9 +330,13 @@ private: std::map> m_functionSigMap; /// Tree of objects and their scopes std::vector> m_objectScopeTree; - // 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_modOutputParams = 5; + /// Maximum number of function calls permissible to keep a check on program size. + static unsigned constexpr s_maxFunctionCalls = 3; + /// Lower bound for function statement count to be considered non-trivial + static unsigned constexpr s_minStatements = 5; /// 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 @@ -339,6 +344,8 @@ private: bool m_inForBodyScope; // Index used for naming loop variable of bounded for loops unsigned m_numNestedForLoops; + /// Counter to keep track of number of function calls + unsigned m_numFunctionCalls; /// Predicate to keep track of for loop init scope. If true, variable /// or function declarations can not be created. bool m_inForInitScope;