def analyser(self):
        
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print("\n<<<<<<<<<< Analyser: Tainted Variables >>>>>>>>>>")
        
        externalFunctions = AnalyseFunctionDefinition.getAllFunctionDefinitionsWithExternalVisibility()
        publicFunctions = AnalyseFunctionDefinition.getAllFunctionDefinitionsWithPublicVisibility()
        taintedFunctions = externalFunctions + publicFunctions

        taintedVariables = defaultdict(list)
        for function in taintedFunctions:
            taintFlow = TaintPropagate.getTaintPropagationForFunction(function)            
            for item in taintFlow:
                _in = MySet()
                _out = []
                if(item["in"] is not None):
                    for var in item["in"]._set:
                        if(AnalyseVariable.getVariableNameForId(var) != "Error"):
                            _in.add(AnalyseVariable.getVariableNameForId(var), item["in"].idToNodeMapping[var].src)
                if(item["out"] is not None):
                    for var in item["out"]._set:
                        if(AnalyseVariable.getVariableNameForId(var) != "Error"):
                            _out.append(AnalyseVariable.getVariableNameForId(var))

                print("At line: " + str(mapASTSourceToLineNumbers.getLine(int(item["src"].split(":",)[0]))))

                for var in _in._set:
                    print(" Incoming tainted variable: " + var + " defined at line:" + str(mapASTSourceToLineNumbers.getLine(int(_in.idToNodeMapping[var].split(":",)[0]))))
                print(" Outgoing tainted variables: " + str(_out))
                self.statsTaintedVariables.append({
                    "line":str(mapASTSourceToLineNumbers.getLine(int(item["src"].split(":",)[0]))),
                    "info":_out,
                })
Пример #2
0
    def analyser(self):
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print("\n<<<<<<<<<< Analyser: Control Flow Graph >>>>>>>>>>")

        functionCalls = AnalyseFunctionCall.getAllFunctionCalls()
        for functionCall in functionCalls:
            found = True
            if (functionCall.name is not None):
                logging.debug("functionCall: " + functionCall.name)
                node = functionCall.parent
                while (node.nodeType != "FunctionDefinition"):
                    node = node.parent
                    if (isinstance(node, AST)):
                        found = False
                        break
                if (found):
                    self.controlFlowGraph.append({
                        "callerName":
                        node.name,
                        "calleeName":
                        functionCall.name,
                        "line":
                        str(
                            mapASTSourceToLineNumbers.getLine(
                                int(functionCall.src.split(":", )[0])))
                    })

        for item in self.controlFlowGraph:
            print(item)
Пример #3
0
 def test_exceptions(self):
     parseAST = ParseAST()
     astFD = open(self.testPath + ".ast", "r")
     parseResults = parseAST.parse(astFD)
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     mapASTSourceToLineNumbers.analyser(self.testDir + "Contracts/" +
                                        self.testFile + ".sol")
     analyseExternalContractInteractions = AnalyseExternalContractInteractions(
     )
     analyseExternalContractInteractions.analyser()
     self.assertEqual(
         len(analyseExternalContractInteractions.statsTransfers), 1)
     self.assertEqual(
         analyseExternalContractInteractions.statsTransfers[0]["line"], "6")
     self.assertEqual(len(analyseExternalContractInteractions.statsSends),
                      1)
     self.assertEqual(
         analyseExternalContractInteractions.statsSends[0]["line"], "7")
     self.assertEqual(len(analyseExternalContractInteractions.statsCalls),
                      1)
     self.assertEqual(
         analyseExternalContractInteractions.statsCalls[0]["line"], "8")
     self.assertEqual(
         len(analyseExternalContractInteractions.statsDelegateCalls), 1)
     self.assertEqual(
         analyseExternalContractInteractions.statsDelegateCalls[0]["line"],
         "9")
     astFD.close()
Пример #4
0
 def test_selfDestruct(self):
     parseAST = ParseAST()
     astFD = open(self.testPath+".ast","r")
     parseResults = parseAST.parse(astFD)
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     mapASTSourceToLineNumbers.analyser(self.testDir+"Contracts/"+self.testFile+".sol")
     analyseDoSPatterns = AnalyseDoSPatterns()
     analyseDoSPatterns.analyser()
     self.assertEqual(len(analyseDoSPatterns.statsDoSWithUnexpectedRevert), 1)
     self.assertEqual(analyseDoSPatterns.statsDoSWithUnexpectedRevert[0]["line"], "9")
     self.assertEqual(analyseDoSPatterns.statsDoSWithUnexpectedRevert[0]["info"], "send")
     astFD.close()
Пример #5
0
 def test_exceptions(self):
     parseAST = ParseAST()
     astFD = open(self.testPath + ".ast", "r")
     parseResults = parseAST.parse(astFD)
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     mapASTSourceToLineNumbers.analyser(self.testDir + "Contracts/" +
                                        self.testFile + ".sol")
     analyseReentrancy = AnalyseReentrancy()
     analyseReentrancy.analyser()
     self.assertEqual(len(analyseReentrancy.statsPotentialReentrancy), 1)
     self.assertEqual(analyseReentrancy.statsPotentialReentrancy[0]["line"],
                      "8")
     astFD.close()
Пример #6
0
 def test_exceptions(self):
     parseAST = ParseAST()
     astFD = open(self.testPath + ".ast", "r")
     parseResults = parseAST.parse(astFD)
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     mapASTSourceToLineNumbers.analyser(self.testDir + "Contracts/" +
                                        self.testFile + ".sol")
     analyseControlFlowGraph = AnalyseControlFlowGraph()
     analyseControlFlowGraph.analyser()
     self.assertEqual(len(analyseControlFlowGraph.controlFlowGraph), 1)
     for item in analyseControlFlowGraph.controlFlowGraph:
         print(item)
     astFD.close()
Пример #7
0
 def test_exceptions(self):
     parseAST = ParseAST()
     astFD = open(self.testPath+".ast","r")
     parseResults = parseAST.parse(astFD)
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     mapASTSourceToLineNumbers.analyser(self.testDir+"Contracts/"+self.testFile+".sol")
     analyseDeprecatedConstructs = AnalyseDeprecatedConstructs()
     analyseDeprecatedConstructs.analyser()
     self.assertEqual(len(analyseDeprecatedConstructs.statsTxOrigin), 1)
     self.assertEqual(analyseDeprecatedConstructs.statsTxOrigin[0]["line"], "21")
     self.assertEqual(len(analyseDeprecatedConstructs.statsBlockMembers), 1)
     self.assertEqual(analyseDeprecatedConstructs.statsBlockMembers[0]["line"], "7")
     astFD.close()
Пример #8
0
 def test_exceptions(self):
     parseAST = ParseAST()
     astFD = open(self.testPath + ".ast", "r")
     parseResults = parseAST.parse(astFD)
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     mapASTSourceToLineNumbers.analyser(self.testDir + "Contracts/" +
                                        self.testFile + ".sol")
     analyseExceptions = AnalyseExceptions()
     analyseExceptions.analyser()
     self.assertEqual(len(analyseExceptions.statsRequires), 1)
     self.assertEqual(analyseExceptions.statsRequires[0]["line"], "9")
     self.assertEqual(len(analyseExceptions.statsAsserts), 1)
     self.assertEqual(analyseExceptions.statsAsserts[0]["line"], "11")
     self.assertEqual(len(analyseExceptions.statsReverts), 1)
     self.assertEqual(analyseExceptions.statsReverts[0]["line"], "13")
     astFD.close()
Пример #9
0
 def test_exceptions(self):
     parseAST = ParseAST()
     astFD = open(self.testPath + ".ast", "r")
     parseResults = parseAST.parse(astFD)
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     mapASTSourceToLineNumbers.analyser(self.testDir + "Contracts/" +
                                        self.testFile + ".sol")
     analyseUninitialisedStoragePointers = AnalyseUninitialisedStoragePointers(
     )
     analyseUninitialisedStoragePointers.analyser()
     self.assertEqual(
         len(analyseUninitialisedStoragePointers.
             statsUninitialisedStoragePointers), 1)
     self.assertEqual(
         analyseUninitialisedStoragePointers.
         statsUninitialisedStoragePointers[0]["line"], "17")
     astFD.close()
    def analyser(self):
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print("\n<<<<<<<<<< Analyser: Unchecked Selfdestructs >>>>>>>>>>")

        functionCalls = AnalyseFunctionCall.getAllFunctionCalls()
        for functionCall in functionCalls:
            if (functionCall.name == "selfdestruct"):
                print("selfdestruct() at line:" + str(
                    mapASTSourceToLineNumbers.getLine(
                        int(functionCall.src.split(":", )[0]))))
                node = functionCall.parent
                checked = False
                while (node.nodeType != "ContractDefinition"):
                    if (
                            node.nodeType == "IfStatement"
                    ):  # Add check for ifStatementCondition containing ownership check via msg.sender
                        self.statsConditionalCheckedSelfdestructs.append({
                            "line":
                            str(
                                mapASTSourceToLineNumbers.getLine(
                                    int(functionCall.src.split(":", )[0]))),
                            "info":
                            "conditional checked selfdestruct"
                        })
                        print(
                            "selfdestruct likely checked with conditional if()"
                        )
                        checked = True
                        break
                    # Add check for Function Definition containing ownership check in a modifer via msg.sender
                    node = node.parent
                if (checked):
                    continue
                else:
                    self.statsUncheckedSelfdestructs.append({
                        "line":
                        str(
                            mapASTSourceToLineNumbers.getLine(
                                int(functionCall.src.split(":", )[0]))),
                        "info":
                        "Unchecked selfdestruct"
                    })
                    print("Unchecked selfdestruct()")
 def test_exceptions(self):
     parseAST = ParseAST()
     astFD = open(self.testPath + ".ast", "r")
     parseResults = parseAST.parse(astFD)
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     mapASTSourceToLineNumbers.analyser(self.testDir + "Contracts/" +
                                        self.testFile + ".sol")
     analyseDefaultVisibility = AnalyseDefaultVisibility()
     analyseDefaultVisibility.analyser()
     self.assertEqual(
         len(analyseDefaultVisibility.statsDefaultVisibilityForFunction), 1)
     self.assertEqual(
         analyseDefaultVisibility.statsDefaultVisibilityForFunction[0]
         ["line"], "8")
     self.assertEqual(
         len(analyseDefaultVisibility.statsDefaultVisibilityForVariable), 1)
     self.assertEqual(
         analyseDefaultVisibility.statsDefaultVisibilityForVariable[0]
         ["line"], "5")
     astFD.close()
    def analyser(self):
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print("\n<<<<<<<<<< Analyser: Default Visibility >>>>>>>>>>")

        functionDefinitions = AnalyseFunctionDefinition.getAllFunctionDefinitions(
        )
        for function in functionDefinitions:
            if (function.visibility == "public"):
                # Determine if "public" visibility was explicitly specified or implicitly inferred
                # Check if "public" keyword is present between input parameters and return parameters
                parametersSrc = function.parameters.get("src")
                returnParametersSrc = function.returnParameters.get("src")
                found = mapASTSourceToLineNumbers.chkStringPresent(
                    "public", parametersSrc, returnParametersSrc)
                if (not found):
                    self.statsDefaultVisibilityForFunction.append({
                        "line":
                        str(
                            mapASTSourceToLineNumbers.getLine(
                                int(function.src.split(":", )[0]))),
                        "info":
                        "default public visibility for function"
                    })
                    print("Default public visibility for Function: " +
                          function.name + " at line:" + str(
                              mapASTSourceToLineNumbers.getLine(
                                  int(function.src.split(":", )[0]))))

        variableDeclarations = AnalyseVariable.getAllVariables()
        for variable in variableDeclarations:
            if (variable.visibility == "internal" and
                (not (variable.parent.nodeType == "FunctionDefinition"))):
                # Determine if "internal" visibility was explicitly specified or implicitly inferred
                # Check if "internal" keyword is present between type and variable name
                variableSrc = variable.src
                typeSrc = variable.typeName.get("src")
                found = mapASTSourceToLineNumbers.chkStringPresentVariableVisibility(
                    "internal", typeSrc, variableSrc)
                if (not found):
                    self.statsDefaultVisibilityForVariable.append({
                        "line":
                        str(
                            mapASTSourceToLineNumbers.getLine(
                                int(variable.src.split(":", )[0]))),
                        "info":
                        "default public visibility for variable"
                    })
                    print("Default internal visibility for Variable: " +
                          variable.name + " at line:" + str(
                              mapASTSourceToLineNumbers.getLine(
                                  int(variable.src.split(":", )[0]))))
Пример #13
0
 def test_exceptions(self):
     parseAST = ParseAST()
     astFD = open(self.testPath + ".ast", "r")
     parseResults = parseAST.parse(astFD)
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     mapASTSourceToLineNumbers.analyser(self.testDir + "Contracts/" +
                                        self.testFile + ".sol")
     analyseUncheckedSelfdestructs = AnalyseUncheckedSelfdestructs()
     analyseUncheckedSelfdestructs.analyser()
     self.assertEqual(
         len(analyseUncheckedSelfdestructs.
             statsConditionalCheckedSelfdestructs), 1)
     self.assertEqual(
         analyseUncheckedSelfdestructs.
         statsConditionalCheckedSelfdestructs[0]["line"], "13")
     self.assertEqual(
         len(analyseUncheckedSelfdestructs.statsUncheckedSelfdestructs), 1)
     self.assertEqual(
         analyseUncheckedSelfdestructs.statsUncheckedSelfdestructs[0]
         ["line"], "17")
     astFD.close()
Пример #14
0
    def analyser(self):
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print("\n<<<<<<<<<< Analyser: Unchecked Calls >>>>>>>>>>")

        calls = AnalyseExpression.getAllCalls()
        for call in calls:
            print("call() at line:" + str(mapASTSourceToLineNumbers.getLine(int(call.src.split(":",)[0]))))
            node = call.parent
            checked = False
            while(node.nodeType != "ContractDefinition"):
                if(node.nodeType == "FunctionCall" and (node.name == "assert" or node.name == "require")):
                    self.statsAssertCheckedCalls.append({
                        "line":str(mapASTSourceToLineNumbers.getLine(int(call.src.split(":",)[0]))),
                        "info":"assert checked call"
                    })
                    print("call checked with assert() or require()")
                    checked = True
                    break
                if((node.nodeType == "UnaryOperation" or node.nodeType == "BinaryOperation") and node.type == "ifStatementCondition"):
                    self.statsConditionalCheckedCalls.append({
                        "line":str(mapASTSourceToLineNumbers.getLine(int(call.src.split(":",)[0]))),
                        "info":"conditional checked call"
                    })
                    print("call checked with conditional if()")
                    checked = True
                    break
                node = node.parent
            if(checked):
                continue
            else:
                self.statsUncheckedCalls.append({
                    "line":str(mapASTSourceToLineNumbers.getLine(int(call.src.split(":",)[0]))),
                    "info":"Unchecked call"
                })
                print("Unchecked call()")
    def analyser(self):
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print(
            "\n<<<<<<<<<< Analyser: Uninitialised Storage Variables >>>>>>>>>>"
        )

        variables = AnalyseVariable.getAllVariables()

        for variable in variables:
            logging.debug("Variable: " + str(variable))
            logging.debug("stateVariable: " + str(variable.stateVariable))
            logging.debug("storageLocation: " + variable.storageLocation)
            logging.debug("type: " +
                          variable.typeDescriptions.get("typeIdentifier"))
            isVariableUninitialised = True
            parent = variable.parent
            if ((parent.nodeType == "VariableDeclarationStatement"
                 and parent.initialValue != None)
                    or parent.nodeType == "FunctionDefinition"):
                isVariableUninitialised = False
            if (variable.stateVariable is False and isVariableUninitialised and
                (variable.storageLocation == "storage" or
                 (variable.storageLocation == "default" and
                  ("struct" in variable.typeDescriptions.get("typeIdentifier")
                   or "array" in variable.typeDescriptions.get(
                       "typeIdentifier") or "mapping"
                   in variable.typeDescriptions.get("typeIdentifier"))))):
                self.statsUninitialisedStoragePointers.append({
                    "line":
                    str(
                        mapASTSourceToLineNumbers.getLine(
                            int(variable.src.split(":", )[0]))),
                    "info":
                    "uninitialised storage pointer"
                })
                print("Uninitialised storage pointer " + variable.name +
                      " at line:" + str(
                          mapASTSourceToLineNumbers.getLine(
                              int(variable.src.split(":", )[0]))))
    def analyser(self):
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print("\n<<<<<<<<<< Analyser: Exceptions >>>>>>>>>>")

        requires = AnalyseFunctionCall.getAllRequires()
        print("Number of require(): " + str(len(requires)))
        for require in requires:
            print("require() " + " at line:" + str(
                mapASTSourceToLineNumbers.getLine(
                    int(require.src.split(":", )[0]))))
            self.statsRequires.append({
                "line":
                str(
                    mapASTSourceToLineNumbers.getLine(
                        int(require.src.split(":", )[0]))),
                "info":
                "require"
            })

        asserts = AnalyseFunctionCall.getAllAsserts()
        print("Number of assert(): " + str(len(asserts)))
        for _assert in asserts:
            print("assert() " + " at line:" + str(
                mapASTSourceToLineNumbers.getLine(
                    int(_assert.src.split(":", )[0]))))
            self.statsAsserts.append({
                "line":
                str(
                    mapASTSourceToLineNumbers.getLine(
                        int(_assert.src.split(":", )[0]))),
                "info":
                "assert"
            })

        reverts = AnalyseFunctionCall.getAllReverts()
        print("Number of revert(): " + str(len(reverts)))
        for revert in reverts:
            print("revert() " + " at line:" + str(
                mapASTSourceToLineNumbers.getLine(
                    int(revert.src.split(":", )[0]))))
            self.statsReverts.append({
                "line":
                str(
                    mapASTSourceToLineNumbers.getLine(
                        int(revert.src.split(":", )[0]))),
                "info":
                "revert"
            })
 def analyser(self):
     expressions = AnalyseExpression.getAllExpressions()
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     print("\n<<<<<<<<<< Analyser: Reentrancy >>>>>>>>>>")
     
     calls = AnalyseExpression.getAllCalls()
     for call in calls:
         logging.debug("Call at line:" + str(mapASTSourceToLineNumbers.getLine(int(call.src.split(":",)[0]))))
         parent = call.parent
         found = False
         defs = []
         while(True):
             if (parent.nodeType == "ExpressionStatement"):
                 logging.debug("Found ExpressionStatement: " + str(parent.id))
                 found = True
                 break
             if (parent.nodeType == "ContractDefinition"):
                 break
             parent = parent.parent
         if (found):
             defs = DefUseAnalysis.getAllDefintionsAfterStatement(parent)
         defsOfStateVariables = []
         for _def in defs:
             logging.debug("_def: " + str(_def))
             logging.debug("Def: " + _def["name"] + " at line:" + str(mapASTSourceToLineNumbers.getLine(int(_def["src"].split(":",)[0]))))
             variableID = _def["referencedDeclaration"]
             variables = AnalyseVariable.getAllVariables()
             for variable in variables:
                 if (variableID == variable.id and variable.stateVariable):
                     defsOfStateVariables.append(_def)
         if (len(defsOfStateVariables) != 0):
             self.statsPotentialReentrancy.append({
                 "line":str(mapASTSourceToLineNumbers.getLine(int(call.src.split(":",)[0]))),
                 "info":"potential reentrancy: state change after call()"
             })
             print("Potential Reentrancy: State change after call()")
         else:
             print("No Reentrancy: No state change after call()")
Пример #18
0
 def test_exceptions(self):
     parseAST = ParseAST()
     astFD = open(self.testPath + ".ast", "r")
     parseResults = parseAST.parse(astFD)
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     mapASTSourceToLineNumbers.analyser(self.testDir + "Contracts/" +
                                        self.testFile + ".sol")
     analyseTaintedVariables = AnalyseTaintedVariables()
     analyseTaintedVariables.analyser()
     self.assertEqual(len(analyseTaintedVariables.statsTaintedVariables), 6)
     self.assertEqual(
         len(analyseTaintedVariables.statsTaintedVariables[0]["info"]), 1)
     self.assertEqual(
         len(analyseTaintedVariables.statsTaintedVariables[1]["info"]), 2)
     self.assertEqual(
         len(analyseTaintedVariables.statsTaintedVariables[2]["info"]), 3)
     self.assertEqual(
         len(analyseTaintedVariables.statsTaintedVariables[3]["info"]), 3)
     self.assertEqual(
         len(analyseTaintedVariables.statsTaintedVariables[4]["info"]), 4)
     self.assertEqual(
         len(analyseTaintedVariables.statsTaintedVariables[5]["info"]), 5)
     astFD.close()
    def analyser(self):
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print("\n<<<<<<<<<< Analyser: DoS Patterns >>>>>>>>>>")

        print("\n********** DoS Patterns with send()/transfer() **********")
        sends = AnalyseExpression.getAllSends()
        for send in sends:
            print("send() at line:" + str(mapASTSourceToLineNumbers.getLine(int(send.src.split(":",)[0]))))
            node = send.parent
            while(node.nodeType != "ContractDefinition"):
                if(node.nodeType == "WhileStatement" or node.nodeType == "ForStatement"):
                    self.statsDoSWithBlockGasLimit.append({
                        "line":str(mapASTSourceToLineNumbers.getLine(int(send.src.split(":",)[0]))),
                        "info":"send"
                    })
                    print("send() within loops are susceptible to DoS with block gas limit")
                    break
                if((node.nodeType == "FunctionCall" and node.name == "require")):
                    self.statsDoSWithUnexpectedRevert.append({
                        "line":str(mapASTSourceToLineNumbers.getLine(int(send.src.split(":",)[0]))),
                        "info":"send"
                    })
                    print("Potential DoS with (unexpected) revert")
                    break
                node = node.parent
        transfers = AnalyseExpression.getAllTransfers()
        for transfer in transfers:
            print("transfer() at line:" + str(mapASTSourceToLineNumbers.getLine(int(transfer.src.split(":",)[0]))))
            self.statsDoSWithUnexpectedRevert.append({
                "line":str(mapASTSourceToLineNumbers.getLine(int(transfer.src.split(":",)[0]))),
                "info":"transfer"
            })
            print("Potential DoS with (unexpected) revert")
            node = transfer.parent
            while(node.nodeType != "ContractDefinition"):
                if(node.nodeType == "WhileStatement" or node.nodeType == "ForStatement"):
                    self.statsDoSWithBlockGasLimit.append({
                        "line":str(mapASTSourceToLineNumbers.getLine(int(transfer.src.split(":",)[0]))),
                        "info":"transfer"
                    })
                    print("transfer() within loops are susceptible to DoS with block gas limit")
                    break
                node = node.parent
    def analyser(self):
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print("\n<<<<<<<<<< Analyser: Unchecked Deprecated Constructs >>>>>>>>>>")

        print("\n********** Use of tx.origin **********")
        constructs = AnalyseExpression.getAllTxOrigins()
        for construct in constructs:
            self.statsTxOrigin.append({
                "line":str(mapASTSourceToLineNumbers.getLine(int(construct.src.split(":",)[0]))),
                "info":"tx.origin"
            })
            print("tx.origin at line:" + str(mapASTSourceToLineNumbers.getLine(int(construct.src.split(":",)[0]))))


        print("\n********** Use of block.<member> where member is number/hash/gaslimit/coinbase/timestamp **********")
        constructs = AnalyseExpression.getAllBlockMembers()
        for construct in constructs:
            self.statsBlockMembers.append({
                "line":str(mapASTSourceToLineNumbers.getLine(int(construct.src.split(":",)[0]))),
                "info":"block.<member>"
            })
            print("Predictable block member at line:" + str(mapASTSourceToLineNumbers.getLine(int(construct.src.split(":",)[0]))))
Пример #21
0
    def analyse(self):
        parseAST = ParseAST()
        astFD = open(self.astFile,"r")
        parseResults = parseAST.parse(astFD)
        
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        mapASTSourceToLineNumbers.analyser(self.inputFile)

        if (self.runAllAnalysers or self.runAnalyser1):
            analyseContractFeatures = AnalyseContractFeatures()
            analyseContractFeatures.analyser()
            
        if (self.runAllAnalysers or self.runAnalyser2):
            analyseControlFlowGraph = AnalyseControlFlowGraph()
            analyseControlFlowGraph.analyser()

        if (self.runAllAnalysers or self.runAnalyser3):
            analyseDefaultVisibility = AnalyseDefaultVisibility()
            analyseDefaultVisibility.analyser()

        if (self.runAllAnalysers or self.runAnalyser4):
            analyseDeprecatedConstructs = AnalyseDeprecatedConstructs()
            analyseDeprecatedConstructs.analyser()

        if (self.runAllAnalysers or (self.runAnalyser5 or self.runAnalyser6 or self.runAnalyser7)):
            analyseDoSPatterns = AnalyseDoSPatterns()
            analyseDoSPatterns.analyser()

        if (self.runAllAnalysers or self.runAnalyser8):
            analyseExternalContractInteractions = AnalyseExternalContractInteractions()
            analyseExternalContractInteractions.analyser()

        if (self.runAllAnalysers or self.runAnalyser9):
            analyseExceptions = AnalyseExceptions()
            analyseExceptions.analyser()

        if (self.runAllAnalysers or self.runAnalyser10):
            analyseReentrancy = AnalyseReentrancy()
            analyseReentrancy.analyser()

        if (self.runAllAnalysers or self.runAnalyser11):
            analyseUncheckedCalls = AnalyseUncheckedCalls()
            analyseUncheckedCalls.analyser()

        if (self.runAllAnalysers or self.runAnalyser12):
            analyseUncheckedSelfdestructs = AnalyseUncheckedSelfdestructs()
            analyseUncheckedSelfdestructs.analyser()

        if (self.runAllAnalysers or self.runAnalyser13):
            analyseUninitialisedStoragePointers = AnalyseUninitialisedStoragePointers()
            analyseUninitialisedStoragePointers.analyser()

        if (self.runAllAnalysers or self.runAnalyser14):
            analyseDefsUses = AnalyseDefsUses()
            analyseDefsUses.analyser()

        if (self.runAllAnalysers or self.runAnalyser15):
            analyseTaintVariables = AnalyseTaintedVariables()
            analyseTaintVariables.analyser()

        astFD.close()
 def analyser(self):
     mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
     print("\n<<<<<<<<<< Analyser: Contract Features >>>>>>>>>>")
     
     contracts = AnalyseContract.getAllContracts()
     for contract in contracts:
         self.statsContractDefinitions.append({
             "line":str(mapASTSourceToLineNumbers.getLine(int(contract.src.split(":",)[0]))),
             "info":"contract definition"
         })
         print("\n********** Contract Features **********")
         print("Contract definition: " + contract.name  + " at line:" + str(mapASTSourceToLineNumbers.getLine(int(contract.src.split(":",)[0]))))
     
     functionDefinitions = AnalyseFunctionDefinition.getAllFunctionDefinitions()
     for function in functionDefinitions:
         self.statsFunctionDefinitions.append({
             "line":str(mapASTSourceToLineNumbers.getLine(int(function.src.split(":",)[0]))),
             "info":"function definition"
         })
         print("\n********** Function Features **********")
         print("Function definition: " + function.name  + " at line:" + str(mapASTSourceToLineNumbers.getLine(int(function.src.split(":",)[0]))))
         if (function.isConstructor):
             self.statsConstructors.append({
                 "line":str(mapASTSourceToLineNumbers.getLine(int(function.src.split(":",)[0]))),
                 "info":"constructor definition"
             })
             print("Constructor")
         print("Visibility: " + function.visibility)
         print("State Mutability: " + function.stateMutability)
         if (AnalyseFunctionDefinition.isFallbackFunction(function)):
             self.statsFallbackFunctions.append({
                 "line":str(mapASTSourceToLineNumbers.getLine(int(function.src.split(":",)[0]))),
                 "info":"fallback definition"
             })
             print("Fallback function")
         if (AnalyseFunctionDefinition.isPayableFallbackFunction(function)):
             print("Payable Fallback function")
         modifiers = function.modifiers
         for modifier in modifiers:
             print("Modifier: " + modifier['modifierName']['name'])
                 
     variableDeclarations = AnalyseVariable.getAllVariables()
     for variable in variableDeclarations:
         self.statsVariableDeclarations.append({
             "line":str(mapASTSourceToLineNumbers.getLine(int(variable.src.split(":",)[0]))),
             "info":"variable declaration"
         })
         print("\n********** Variable Features **********")
         print("Variable declaration: " + variable.name  + " at line:" + str(mapASTSourceToLineNumbers.getLine(int(variable.src.split(":",)[0]))))
         if (variable.stateVariable):
             self.statsStateVariables.append({
                 "line":str(mapASTSourceToLineNumbers.getLine(int(variable.src.split(":",)[0]))),
                 "info":"state variable declaration"
             })
             print("State variable")
         else:
             if (variable.parent.nodeType == "FunctionDefinition"):
                 print("Function parameter")
             else:
                 print("Local variable")
    def analyser(self):
        expressions = AnalyseExpression.getAllExpressions()
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print(
            "\n<<<<<<<<<< Analyser: External Contract Interactions >>>>>>>>>>")

        transfers = AnalyseExpression.getAllTransfers()
        for transfer in transfers:
            for child in transfer.children:
                if (child.nodeType == "Identifier"):
                    self.statsTransfers.append({
                        "line":
                        str(
                            mapASTSourceToLineNumbers.getLine(
                                int(child.src.split(":", )[0]))),
                        "info":
                        "transfer"
                    })
                    print("Transfer to " + child.name + " at line:" + str(
                        mapASTSourceToLineNumbers.getLine(
                            int(child.src.split(":", )[0]))))

        sends = AnalyseExpression.getAllSends()
        for send in sends:
            for child in send.children:
                if (child.nodeType == "Identifier"):
                    self.statsSends.append({
                        "line":
                        str(
                            mapASTSourceToLineNumbers.getLine(
                                int(child.src.split(":", )[0]))),
                        "info":
                        "send"
                    })
                    print("Send to " + child.name + " at line:" + str(
                        mapASTSourceToLineNumbers.getLine(
                            int(child.src.split(":", )[0]))))

        calls = AnalyseExpression.getAllCalls()
        for call in calls:
            for child in call.children:
                if (child.nodeType == "Identifier"):
                    self.statsCalls.append({
                        "line":
                        str(
                            mapASTSourceToLineNumbers.getLine(
                                int(child.src.split(":", )[0]))),
                        "info":
                        "call"
                    })
                    print("Call to " + child.name + " at line:" + str(
                        mapASTSourceToLineNumbers.getLine(
                            int(child.src.split(":", )[0]))))

        delegateCalls = AnalyseExpression.getAllDelegateCalls()
        for delegateCall in delegateCalls:
            for child in delegateCall.children:
                if (child.nodeType == "Identifier"):
                    self.statsDelegateCalls.append({
                        "line":
                        str(
                            mapASTSourceToLineNumbers.getLine(
                                int(child.src.split(":", )[0]))),
                        "info":
                        "delegateCall"
                    })
                    print("DelegateCall to " + child.name + " at line:" + str(
                        mapASTSourceToLineNumbers.getLine(
                            int(child.src.split(":", )[0]))))
    def analyser(self):
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        print("\n<<<<<<<<<< Analyser: Defs and Uses >>>>>>>>>>")
        
        functionDefinitions = AnalyseFunctionDefinition.getAllFunctionDefinitions()

        for function in functionDefinitions:
            print("\n********** Function Defs/Uses **********")
            print("Function definition: " + function.name  + " at line:" + str(mapASTSourceToLineNumbers.getLine(int(function.src.split(":",)[0]))))
            dataflow = DefUseAnalysis.getDataflowForFunction(function)
            if (self.loggingLevel == "DEBUG"):
                print("Dataflow length: " + str(len(dataflow)))
                for item in dataflow:
                    _gen = []
                    _kill = []
                    _in = MySet()
                    _out = []
                    if(item["gen"] is not None and item["gen"]._set is not None):
                        for var in item["gen"]._set:
                            if(AnalyseVariable.getVariableNameForId(var) != "Error"):
                                _gen.append(AnalyseVariable.getVariableNameForId(var))
                    if(item["kill"] is not None):
                        for var in item["kill"]._set:
                            if(AnalyseVariable.getVariableNameForId(var) != "Error"):
                                _kill.append(AnalyseVariable.getVariableNameForId(var))
                    if(item["in"] is not None):
                        for var in item["in"]._set:
                            if(AnalyseVariable.getVariableNameForId(var) != "Error"):
                                _in.add(AnalyseVariable.getVariableNameForId(var), item["in"].idToNodeMapping[var].src)
                    if(item["out"] is not None):
                        for var in item["out"]._set:
                            if(AnalyseVariable.getVariableNameForId(var) != "Error"):
                                _out.append(AnalyseVariable.getVariableNameForId(var))
                    print("Node Id: " +
                          str(item["id"]) + 
                          " at line:" +
                          str(mapASTSourceToLineNumbers.getLine(int(item["src"].split(":",)[0]))) +
                          " gen: " + str(_gen) +
                          " kill: " + str(_kill)
                    )
                
                for var in _in._set:
                    print("in: " + var + " defined at line:" + str(mapASTSourceToLineNumbers.getLine(int(_in.idToNodeMapping[var].split(":",)[0]))))
                print(" out: " + str(_out))


            defs = []
            defs = DefUseAnalysis.getAllDefsAtNode(function, defs)
            for _def in defs:
                self.statsDefs.append({
                    "line":str(mapASTSourceToLineNumbers.getLine(int(_def["src"].split(":",)[0]))),
                    "info":_def["name"]
                })
                if(self.loggingLevel == "DEBUG"):
                    print("Def: " + _def["name"] + " at line:" + str(mapASTSourceToLineNumbers.getLine(int(_def["src"].split(":",)[0]))))
            
            uses = []
            uses = DefUseAnalysis.getAllUsesAtNode(function, uses)
            for use in uses:
                self.statsUses.append({
                    "line":str(mapASTSourceToLineNumbers.getLine(int(use["src"].split(":",)[0]))),
                    "info":use["name"]
                })
                print("Use: " +
                      use["name"] +
                      " at line:" + str(mapASTSourceToLineNumbers.getLine(int(use["src"].split(":",)[0]))))
                print(" > Using value from definition on line: ",end='')
                line = mapASTSourceToLineNumbers.getLine(int(use["src"].split(":",)[0]))
                varRef = use["referencedDeclaration"]
                found = False
                for item in dataflow:
                    if(mapASTSourceToLineNumbers.getLine(int(item["src"].split(":",)[0])) == line):
                        if(item["in"] and varRef in item["in"]._set):
                            print(mapASTSourceToLineNumbers.getLine(int(item["in"].idToNodeMapping[varRef].src.split(":",)[0])))
                            found = True
                            break
                if(not found):
                    print("Not Found")
    def test_exceptions(self):
        parseAST = ParseAST()
        astFD = open(self.testPath + ".ast", "r")
        parseResults = parseAST.parse(astFD)
        mapASTSourceToLineNumbers = MapASTSourceToLineNumbers()
        mapASTSourceToLineNumbers.analyser(self.testDir + "Contracts/" +
                                           self.testFile + ".sol")
        analyseDefsUses = AnalyseDefsUses()
        analyseDefsUses.analyser()
        self.assertEqual(len(analyseDefsUses.statsDefs), 16)
        self.assertEqual(analyseDefsUses.statsDefs[0]["line"], "14")
        self.assertEqual(analyseDefsUses.statsDefs[0]["info"], "k")
        self.assertEqual(analyseDefsUses.statsDefs[1]["line"], "18")
        self.assertEqual(analyseDefsUses.statsDefs[1]["info"], "i")
        self.assertEqual(analyseDefsUses.statsDefs[2]["line"], "21")
        self.assertEqual(analyseDefsUses.statsDefs[2]["info"], "a")
        self.assertEqual(analyseDefsUses.statsDefs[3]["line"], "22")
        self.assertEqual(analyseDefsUses.statsDefs[3]["info"], "a")
        self.assertEqual(analyseDefsUses.statsDefs[4]["line"], "23")
        self.assertEqual(analyseDefsUses.statsDefs[4]["info"], "j")
        self.assertEqual(analyseDefsUses.statsDefs[5]["line"], "24")
        self.assertEqual(analyseDefsUses.statsDefs[5]["info"], "a")
        self.assertEqual(analyseDefsUses.statsDefs[6]["line"], "25")
        self.assertEqual(analyseDefsUses.statsDefs[6]["info"], "i")
        self.assertEqual(analyseDefsUses.statsDefs[7]["line"], "28")
        self.assertEqual(analyseDefsUses.statsDefs[7]["info"], "i")
        self.assertEqual(analyseDefsUses.statsDefs[8]["line"], "31")
        self.assertEqual(analyseDefsUses.statsDefs[8]["info"], "j")
        self.assertEqual(analyseDefsUses.statsDefs[9]["line"], "34")
        self.assertEqual(analyseDefsUses.statsDefs[9]["info"], "a")
        self.assertEqual(analyseDefsUses.statsDefs[10]["line"], "35")
        self.assertEqual(analyseDefsUses.statsDefs[10]["info"], "j")
        self.assertEqual(analyseDefsUses.statsDefs[11]["line"], "38")
        self.assertEqual(analyseDefsUses.statsDefs[11]["info"], "data")
        self.assertEqual(analyseDefsUses.statsDefs[12]["line"], "40")
        self.assertEqual(analyseDefsUses.statsDefs[12]["info"], "balances")
        self.assertEqual(analyseDefsUses.statsDefs[13]["line"], "40")
        self.assertEqual(analyseDefsUses.statsDefs[13]["info"], "msg")
        self.assertEqual(analyseDefsUses.statsDefs[14]["line"], "41")
        self.assertEqual(analyseDefsUses.statsDefs[14]["info"], "balances")
        self.assertEqual(analyseDefsUses.statsDefs[15]["line"], "41")
        self.assertEqual(analyseDefsUses.statsDefs[15]["info"], "i")

        self.assertEqual(len(analyseDefsUses.statsUses), 22)
        self.assertEqual(analyseDefsUses.statsUses[0]["line"], "15")
        self.assertEqual(analyseDefsUses.statsUses[0]["info"], "k")
        self.assertEqual(analyseDefsUses.statsUses[1]["line"], "21")
        self.assertEqual(analyseDefsUses.statsUses[1]["info"], "i")
        self.assertEqual(analyseDefsUses.statsUses[2]["line"], "22")
        self.assertEqual(analyseDefsUses.statsUses[2]["info"], "a")
        self.assertEqual(analyseDefsUses.statsUses[3]["line"], "23")
        self.assertEqual(analyseDefsUses.statsUses[3]["info"], "i")
        self.assertEqual(analyseDefsUses.statsUses[4]["line"], "24")
        self.assertEqual(analyseDefsUses.statsUses[4]["info"], "a")
        self.assertEqual(analyseDefsUses.statsUses[5]["line"], "24")
        self.assertEqual(analyseDefsUses.statsUses[5]["info"], "i")
        self.assertEqual(analyseDefsUses.statsUses[6]["line"], "24")
        self.assertEqual(analyseDefsUses.statsUses[6]["info"], "j")
        self.assertEqual(analyseDefsUses.statsUses[7]["line"], "25")
        self.assertEqual(analyseDefsUses.statsUses[7]["info"], "a")
        self.assertEqual(analyseDefsUses.statsUses[8]["line"], "25")
        self.assertEqual(analyseDefsUses.statsUses[8]["info"], "i")
        self.assertEqual(analyseDefsUses.statsUses[9]["line"], "25")
        self.assertEqual(analyseDefsUses.statsUses[9]["info"], "j")
        self.assertEqual(analyseDefsUses.statsUses[10]["line"], "25")
        self.assertEqual(analyseDefsUses.statsUses[10]["info"], "msg")
        self.assertEqual(analyseDefsUses.statsUses[11]["line"], "27")
        self.assertEqual(analyseDefsUses.statsUses[11]["info"], "a")
        self.assertEqual(analyseDefsUses.statsUses[12]["line"], "28")
        self.assertEqual(analyseDefsUses.statsUses[12]["info"], "i")
        self.assertEqual(analyseDefsUses.statsUses[13]["line"], "31")
        self.assertEqual(analyseDefsUses.statsUses[13]["info"], "bar")
        self.assertEqual(analyseDefsUses.statsUses[14]["line"], "31")
        self.assertEqual(analyseDefsUses.statsUses[14]["info"], "a")
        self.assertEqual(analyseDefsUses.statsUses[15]["line"], "31")
        self.assertEqual(analyseDefsUses.statsUses[15]["info"], "a")
        self.assertEqual(analyseDefsUses.statsUses[16]["line"], "34")
        self.assertEqual(analyseDefsUses.statsUses[16]["info"], "a")
        self.assertEqual(analyseDefsUses.statsUses[17]["line"], "35")
        self.assertEqual(analyseDefsUses.statsUses[17]["info"], "j")
        self.assertEqual(analyseDefsUses.statsUses[18]["line"], "38")
        self.assertEqual(analyseDefsUses.statsUses[18]["info"], "j")
        self.assertEqual(analyseDefsUses.statsUses[19]["line"], "40")
        self.assertEqual(analyseDefsUses.statsUses[19]["info"], "j")
        self.assertEqual(analyseDefsUses.statsUses[20]["line"], "41")
        self.assertEqual(analyseDefsUses.statsUses[20]["info"], "i")
        self.assertEqual(analyseDefsUses.statsUses[21]["line"], "41")
        self.assertEqual(analyseDefsUses.statsUses[21]["info"], "a")
        astFD.close()