def advancedUpdateEth_2(self, function): from slither.analyses.data_dependency.data_dependency import is_dependent allNodes = function.nodes for ethNode in function.ethNodes: entryPointToethNode = [] entryPointToethNode.append(function.entry_point) pilotProcessNodes = list( set(allNodes) - set([function.entry_point, ethNode])) entryPointToethNode.extend(pilotProcessNodes) entryPointToethNode.append(ethNode) adjMatrix = getadjMatrix(entryPointToethNode) mydeepGraph = MyDeepGraph(len(entryPointToethNode)) mydeepGraph.setadjMetrix(adjMatrix) allPaths = mydeepGraph.getPathofTwoNode( 0, len(entryPointToethNode) - 1) allPaths_Node = allPaths_intToNode(allPaths, entryPointToethNode) for path in allPaths_Node: for ir in path[-1].irs: if isinstance( ir, (HighLevelCall, LowLevelCall, Transfer, Send)): if ir.call_value: for node in path[0:len(path) - 1]: for stateVariableWritten in node.state_variables_written: if is_dependent(ir.call_value, stateVariableWritten, function.contract): return True # elif is_dependent(stateVariableWritten, ir.call_value, function.contract): # return True return False
def detect_reentrancy(self, contract, ethNodeList, taintNodeList, callGraph): print('Start Contract {}'.format(contract.name)) for function in contract.functions: if function.is_implemented: print('\tTo analyze:{}.{}'.format(function.contract.name, function.full_name)) dm = DM(function) # 声明dm防御对象 reentrancyFlag = False # for node in function.nodes: # self._node_taint(node) function_ethNodeList = [] # 存储本函数体内的eth functon_taintNodeList = [] # 存储本函数体内的taint for node in function.nodes: if node in taintNodeList: functon_taintNodeList.append(node) if node in ethNodeList: function_ethNodeList.append(node) # for function_taintNode in functon_taintNodeList: ''' startToend = [start, ... ,end] ''' cfgEntryNodeTotaint = [] cfgEntryNodeTotaint.append(function.entry_point) cfgEntryNodeTotaint.extend(list(set(function.nodes) - set([function.entry_point, function_taintNode]))) cfgEntryNodeTotaint.append(function_taintNode) adjMatrix = getadjMatrix(cfgEntryNodeTotaint) mydeepGraph = MyDeepGraph(len(cfgEntryNodeTotaint)) mydeepGraph.setadjMetrix(adjMatrix) cfgAllPath = mydeepGraph.getPathofTwoNode(0, len(cfgEntryNodeTotaint)-1) cfgAllPath_Node = allPaths_intToNode(cfgAllPath, cfgEntryNodeTotaint) cfgCandidateAllPath_Node = [] for path in cfgAllPath_Node[:]: if any(iNode in ethNodeList for iNode in path): cfgCandidateAllPath_Node.append(path) if cfgCandidateAllPath_Node: # 证明cfg本身就找到Reentrancy了,准备humanlook, 注意reversed, DM human_cfgCandidateAllPath_Node = [] for path in cfgCandidateAllPath_Node: tempPath = [] for everyNode in path: if everyNode.type == NodeType.ENTRYPOINT: everyNode.add_expression('entryPoint') tempPath.append(str(everyNode.expression)) human_cfgCandidateAllPath_Node.append(tempPath) advanceUpdateFlag = dm.advancedUpdateEth(function) privateVisibility = dm.privateVisibility(function) havePublicCaller = callerVisibilityHavePublic(function, callGraph, dm) haveDefenModifier = dm.haveDefenseModifier(function) haveDefenRequire = dm.requireMsgSender(function) #ethAdvanceUpdateFlag = dm.advancedUpdateEth_2(function) if privateVisibility is True or haveDefenModifier is True or haveDefenRequire is True: # print('privateVisibility: ', privateVisibility) # print('haveDefenModifier: ', haveDefenModifier) # print('haveDefenRequire: ', haveDefenRequire) # print('function.is_protected() ', function.is_protected()) # accessPermision = True # havePublicCaller = True if havePublicCaller is True: reentrancyFlag = True print('\t\tcontract: {} | function: {} | accessPermision: {} | publicCaller: {} | 锁: {} '.format( function.contract.name, function.full_name, accessPermision, havePublicCaller, advanceUpdateFlag)) for human_cfgCandidatePath_Node in human_cfgCandidateAllPath_Node: print('\t\t\tpath: {}'.format(human_cfgCandidatePath_Node)) else: accessPermision = False reentrancyFlag = True print( '\t\tcontract: {} | function: {} | accessPermision: {} | 锁: {}'.format( function.contract.name, function.full_name, accessPermision, advanceUpdateFlag)) for human_cfgCandidatePath_Node in human_cfgCandidateAllPath_Node: print('\t\t\tpath: {}'.format(human_cfgCandidatePath_Node)) if reentrancyFlag is True: print('[cfg_Reentrancy in] contract: {} . function: {} | {}'.format(function.contract.name, function.full_name, function.source_mapping_str)) continue if reentrancyFlag is False: # 证明cfg本身没找到Reentrancy careTaintNode = set() careEthNode = set() careTaintFunction = set() careEthFunction = set() callGraphToTaintAllPath_Node = [] callGraphToEthAllPath_Node = [] print('\t\tcfg分析安全,所以开始ICFG的分析'.format(function.full_name)) currentFunctionNode = callGraph.function_Map_node.get(function) ''' 把钱更新的那些个ethFunction剔除掉 ''' for ethFunctionNode in callGraph.ethFunctionNodes[:]: if dm.advancedUpdateEth(ethFunctionNode.function):# or dm.advancedUpdateEth_2(ethFunctionNode.function): callGraph.ethFunctionNodes.remove(ethFunctionNode) # for taintFunctionNode in callGraph.taintFunctionNodes[:]: # if dm.requireMsgSender(taintFunctionNode.function): # callGraph.taintFunctionNodes.remove(taintFunctionNode) for taintFunctionNode in callGraph.taintFunctionNodes: functionNode_to_taintFunctionNode = [] functionNode_to_taintFunctionNode.append(currentFunctionNode) functionNode_to_taintFunctionNode.extend(list(set(callGraph.functionNodes) - set([currentFunctionNode, taintFunctionNode]))) functionNode_to_taintFunctionNode.append(taintFunctionNode) adjMatrix = getadjMatrix(functionNode_to_taintFunctionNode) mydeepGraph = MyDeepGraph(len(functionNode_to_taintFunctionNode)) mydeepGraph.setadjMetrix(adjMatrix) callGraphToOneofTaintAllPath = mydeepGraph.getPathofTwoNode(0, len(functionNode_to_taintFunctionNode) - 1) callGraphToOneofTaintAllPath_Node = allPaths_intToNode(callGraphToOneofTaintAllPath, functionNode_to_taintFunctionNode) callGraphToTaintAllPath_Node.extend(callGraphToOneofTaintAllPath_Node) for ethFunctionNode in callGraph.ethFunctionNodes: functionNode_to_ethFunctionNode = [] functionNode_to_ethFunctionNode.append(currentFunctionNode) functionNode_to_ethFunctionNode.extend(list(set(callGraph.functionNodes) - set([currentFunctionNode, ethFunctionNode]))) functionNode_to_ethFunctionNode.append(ethFunctionNode) adjMatrix = getadjMatrix(functionNode_to_ethFunctionNode) mydeepGraph = MyDeepGraph(len(functionNode_to_ethFunctionNode)) mydeepGraph.setadjMetrix(adjMatrix) callGraphToOneOfEthAllPath = mydeepGraph.getPathofTwoNode(0, len(functionNode_to_ethFunctionNode) - 1) callGraphToOneofEthAllPath_Node = allPaths_intToNode(callGraphToOneOfEthAllPath, functionNode_to_ethFunctionNode) callGraphToEthAllPath_Node.extend(callGraphToOneofEthAllPath_Node) for path in callGraphToTaintAllPath_Node: careTaintFunction.add(path[1].function) for path in callGraphToEthAllPath_Node: careEthFunction.add(path[1].function) for node in function.nodes: for highLevelCall in node.high_level_calls: contract, functionOrVariable = highLevelCall if isinstance(functionOrVariable, Function): if functionOrVariable in careEthFunction: careEthNode.add(node) if functionOrVariable in careTaintFunction: careTaintNode.add(node) for internalCall in node.internal_calls: if isinstance(internalCall, Function): if internalCall in careEthFunction: careEthNode.add(node) if internalCall in careTaintFunction: careTaintNode.add(node) careTaintNode = careTaintNode | set(functon_taintNodeList) careEthNode = careEthNode | set(function_ethNodeList) for taintNode in careTaintNode: cfgEntryNodeTotaint = [] cfgEntryNodeTotaint.append(function.entry_point) cfgEntryNodeTotaint.extend(list(set(function.nodes) - set([function.entry_point, taintNode]))) cfgEntryNodeTotaint.append(taintNode) adjMatrix = getadjMatrix(cfgEntryNodeTotaint) mydeepGraph = MyDeepGraph(len(cfgEntryNodeTotaint)) mydeepGraph.setadjMetrix(adjMatrix) cfgAllPath = mydeepGraph.getPathofTwoNode(0, len(cfgEntryNodeTotaint) - 1) cfgAllPath_Node = allPaths_intToNode(cfgAllPath, cfgEntryNodeTotaint) corePath = [] for path in cfgAllPath_Node: if any(cfgNode in careEthNode for cfgNode in path[0:len(path)-1]): corePath.append(path) if corePath: ################################################### ######################################## for path in corePath[:]: for callee in path[-1].callee: calleefunctionNode = callGraph.function_Map_node.get(callee) for callGraphToTaintPath in callGraphToTaintAllPath_Node: if calleefunctionNode == callGraphToTaintPath[1]: afterCalleeList = [functionNode.function.full_name for functionNode in callGraphToTaintPath[1:]] afterCalleeList.insert(0, 'taint') path.append(afterCalleeList) for tempP in corePath[:]: for tempNode in tempP: if tempNode in list(careEthNode): for callee in tempNode.callee: calleefunctionNode = callGraph.function_Map_node.get(callee) for callGraphToEthPath in callGraphToEthAllPath_Node: if calleefunctionNode == callGraphToEthPath[1]: afterCalleeList = [functionNode.function.full_name for functionNode in callGraphToEthPath[1:]] afterCalleeList.insert(0, 'eth') tempP.append(afterCalleeList) ########################################## human_corePath = [] for path in corePath: ############################################## tempPath = [] needindex = len(path) for i in range(len(path)): if isinstance(path[i], list): needindex = i break ######################### for cfgNode in path[0:needindex]: tempPath.append(str(cfgNode.expression)) tempPath.append(path[needindex:]) human_corePath.append(tempPath) advanceUpdateFlag = False # dm.advancedUpdateEth(function) privateVisibility = dm.privateVisibility(function) haveDefenModifier = dm.haveDefenseModifier(function) havePublicCaller = callerVisibilityHavePublic(function, callGraph, dm) haveDefenRequire = dm.requireMsgSender(function) if privateVisibility is True or haveDefenModifier is True or haveDefenRequire is True: accessPermision = True if havePublicCaller is True: reentrancyFlag = True print( '\t\tcontract: {} | function: {} | accessPermision: {} | publicCaller: {} | 锁/钱提前更新:{}'.format( function.contract.name, function.full_name, accessPermision, havePublicCaller, advanceUpdateFlag)) for humanPath in human_corePath: print('\t\t\tpath:{}'.format(humanPath)) else: accessPermision = False reentrancyFlag = True print( '\t\tcontract: {} | function: {} | accessPermision: {} | 锁/钱提前更新:{}'.format( function.contract.name, function.full_name, accessPermision, advanceUpdateFlag)) for humanPath in human_corePath: print('\t\t\tpath:{}'.format(humanPath)) if reentrancyFlag is True: print('[Icfg_Reentrancy in] contract: {} . function: {} | {}'.format(function.contract.name, function.full_name, function.source_mapping_str)) continue
def detect_reentrancy(self, contract, ethNodeList, taintNodeList, icfg, callGraph, cfgEndNodeList): print('Start Contract {}'.format(contract.name)) for function in contract.functions: if function.is_implemented: print('\tTo analyze:{}.{}'.format(function.contract.name, function.full_name)) dm = DM(function) # 声明dm防御对象 reentrancyFlag = False functon_taintNodeList = [] # 存储本函数体内的taint for node in function.nodes: if node in taintNodeList: functon_taintNodeList.append(node) for function_taintNode in functon_taintNodeList: ''' startToend = [start, ... ,end] ''' cfgEntryNodeTotaint = [] cfgEntryNodeTotaint.append(function.entry_point) cfgEntryNodeTotaint.extend( list( set(function.nodes) - set([function.entry_point, function_taintNode]))) cfgEntryNodeTotaint.append(function_taintNode) # cfgAllPath = getCfgAllPath(cfgEntryNodeTotaint) adjMatrix = getadjMatrix(cfgEntryNodeTotaint) mydeepGraph = MyDeepGraph(len(cfgEntryNodeTotaint)) mydeepGraph.setadjMetrix(adjMatrix) cfgAllPath = mydeepGraph.getPathofTwoNode( 0, len(cfgEntryNodeTotaint) - 1) cfgAllPath_Node = allPaths_intToNode( cfgAllPath, cfgEntryNodeTotaint) cfgCandidateAllPath_Node = [] for path in cfgAllPath_Node[:]: if any(iNode in ethNodeList for iNode in path): cfgCandidateAllPath_Node.append(path) if cfgCandidateAllPath_Node: # 证明cfg本身就找到Reentrancy了,准备humanlook, 注意reversed, DM human_cfgCandidateAllPath_Node = [] for path in cfgCandidateAllPath_Node: tempPath = [] for everyNode in path: if everyNode.type == NodeType.ENTRYPOINT: everyNode.add_expression('entryPoint') tempPath.append(str(everyNode.expression)) human_cfgCandidateAllPath_Node.append(tempPath) advanceUpdateFlag = False # dm.advancedUpdateEth(function) privateVisibility = dm.privateVisibility(function) havePublicCaller = callerVisibilityHavePublic( function, callGraph) if privateVisibility is True: if havePublicCaller is True: reentrancyFlag = True print( '\t\tcontract: {} | function: {} | private: {} | publicCaller: {} | 锁/钱提前更新:{}' .format(function.contract.name, function.full_name, privateVisibility, havePublicCaller, advanceUpdateFlag)) for human_cfgCandidatePath_Node in human_cfgCandidateAllPath_Node: print('\t\t\tpath: {}'.format( human_cfgCandidatePath_Node)) else: reentrancyFlag = True print( '\t\tcontract: {} | function: {} | private: {} | 锁/钱提前更新:{}' .format(function.contract.name, function.full_name, privateVisibility, advanceUpdateFlag)) for human_cfgCandidatePath_Node in human_cfgCandidateAllPath_Node: print('\t\t\tpath: {}'.format( human_cfgCandidatePath_Node)) if reentrancyFlag is True: print( '[cfg_Reentrancy in] contract: {} . function: {} | {}'. format(function.contract.name, function.full_name, function.source_mapping_str)) continue if reentrancyFlag is False: # 证明cfg本身没找到Reentrancy ''' bug修复为了把当前的function的endnode的回调用处的那条路径删除,同时也要删除本函数entryNode的icfgFather ''' print('\t\tcfg分析安全,所以开始ICFG的分析'.format(function.full_name)) # = function.entry_point.icfgFathers # function.entry_point.set_icfgFather([]) ''' endnodeMapBackSons = {} # hh = [str(endnode.expression) for endnode in function.ENDnodes] # print('结束点:'.format(hh)) for endnode in function.ENDnodes: endnodeMapBackSons[endnode] = [] for son in endnode.backIcfgSons: endnodeMapBackSons[endnode].append(son) for endnode in function.ENDnodes: endnode.set_backIcfgSons([]) ''' # tt = [str(taintNode.expression) for taintNode in taintNodeList] # print('系统中所有的taint:{}, 总共有 {} 个taintNode'.format(tt, len(taintNodeList))) # for endnode in function.ENDnodes: # print('回到哪里了: {}'.format(endnodeMapBackSons[endnode])) # for endnode in function.ENDnodes: # print('注意应该是0:{}'.format(len(endnode.backIcfgSons))) for taintNode in taintNodeList: icfgEntryNodeTotaint = [] icfgEntryNodeTotaint.append(function.entry_point) icfgEntryNodeTotaint.extend( list( set(icfg.allNodes) - set([function.entry_point, taintNode]))) icfgEntryNodeTotaint.append(taintNode) adjMatrix = getICFGadjMatrix(icfgEntryNodeTotaint) mydeepGraph = MyDeepGraph(len(icfgEntryNodeTotaint)) mydeepGraph.setadjMetrix(adjMatrix) #mydeepGraph.printMatrix() icfgAllPath = mydeepGraph.getPathofTwoNode( 0, len(icfgEntryNodeTotaint) - 1) icfgAllPath_Node = allPaths_intToNode( icfgAllPath, icfgEntryNodeTotaint) #icfgAllPath = getIcfgAllPath(icfgEntryNodeTotaint) # print('函数{}的入口点到taint点{}的路径有{}条:'.format(function.full_name, taintNode.expression, len(icfgAllPath))) #icfgAllPath_Node = allPaths_intToNode(icfgAllPath, icfgEntryNodeTotaint) # print('应该为1:{}'.format(len(icfgAllPath_Node))) # qq = [[str(ww.expression) for ww in yy] for yy in icfgAllPath_Node] # print('路径:{}'.format(qq)) icfgCandidateAllPath_Node = [] for path in icfgAllPath_Node: if any(iNode in ethNodeList for iNode in path): icfgCandidateAllPath_Node.append(path) # if icfgCandidateAllPaht_Node: # # 检查icfg路径合法性 # cfgEndNodeList_exp = list(set(cfgEndNodeList) - set(function.ENDnodes)) # for path in icfgCandidateAllPaht_Node: # new = path[-1] # for node in path: # if node in cfgEndNodeList_exp: # for entryP in node.icfgSons: # for preEndNode in entryP.function.ENDnodes: # if preEndNode in path: # if (path.index(preEndNode) + 1) <= len(path)-1: # possibleErrNodeIndex = path.index(preEndNode) + 1 # possibleErrNode = path[possibleErrNodeIndex] # if possibleErrNode != node: # # path.append('非法路径') # pass # # # if node in function.ENDnodes: # if path[-1] != node: # # 非法路径 # pass if icfgCandidateAllPath_Node: # 证明icfg本身找到Reentrancy了,准备humanlook, DM # print('证明icfg本身找到Reentrancy了,准备humanlook, DM') ''' 转变成普通人能看懂的形式,注意reversed ''' human_icfgCandidateAllPath_Node = [] for path in icfgCandidateAllPath_Node: tempPath = [] for everyNode in path: if everyNode.type == NodeType.ENTRYPOINT: everyNode.add_expression('entryPoint') tempPath.append(str(everyNode.expression)) human_icfgCandidateAllPath_Node.append( tempPath) etherNodesInPath = [] # for path in icfgCandidateAllPaht_Node: # for itemNode in path: # if itemNode in ethNodeList: # etherNodesInPath.append(itemNode) etherNodesInPath = [ itemNode for path in icfgCandidateAllPath_Node for itemNode in path if itemNode in ethNodeList ] # print('长度:{}'.format(len(etherNodesInPath))) # kkk = [str(etherNodeInPath.expression) for etherNodeInPath in etherNodesInPath] # print('在路径中的转账节点:{}'.format(kkk)) realETHfunctionList = [ eNode.function for eNode in etherNodesInPath ] ''' if all(dm.advancedUpdateEth(function) for function in realETHfunctionList): advanceUpdateFlag = True else: advanceUpdateFlag = False ''' advanceUpdateFlag = False #advanceUpdateFlag = dm.advancedUpdateEth(function) privateVisibility = dm.privateVisibility(function) havePublicCaller = callerVisibilityHavePublic( function, callGraph) if privateVisibility is True: if havePublicCaller is True: reentrancyFlag = True print( '\t\tcontract: {} | function: {} | private: {} | publicCaller: {} | 锁/钱提前更新:{}' .format(function.contract.name, function.full_name, privateVisibility, havePublicCaller, advanceUpdateFlag)) for human_icfgCandidatePath_Node in human_icfgCandidateAllPath_Node: print('\t\t\tpath: {}'.format( human_icfgCandidatePath_Node)) else: reentrancyFlag = True print( '\t\tcontract: {} | function: {} | private: {} | 锁/钱提前更新:{}' .format(function.contract.name, function.full_name, privateVisibility, advanceUpdateFlag)) for human_icfgCandidatePath_Node in human_icfgCandidateAllPath_Node: print('\t\t\tpath: {}'.format( human_icfgCandidatePath_Node)) ''' 为了把当前的function的endnode的回调用处的那条路径再补上, 和entryNode的icfgFather叶去掉 ''' # if endnodeMapBackSons: # for endnode in function.ENDnodes: # endnode.set_backIcfgSons = endnodeMapBackSons[endnode] #function.entry_point.set_icfgFather = icfgFathersNeedToDuan if reentrancyFlag is True: print( '[icfg_Reentrancy in] contract: {} . function: {} | {}' .format(function.contract.name, function.name, function.source_mapping_str))
def advancedUpdateEth(self, function): from slither.analyses.data_dependency.data_dependency import is_dependent allNodes = function.nodes for ethNode in function.ethNodes: entryPointToethNode = [] entryPointToethNode.append(function.entry_point) pilotProcessNodes = list( set(allNodes) - set([function.entry_point, ethNode])) entryPointToethNode.extend(pilotProcessNodes) entryPointToethNode.append(ethNode) adjMatrix = getadjMatrix(entryPointToethNode) mydeepGraph = MyDeepGraph(len(entryPointToethNode)) mydeepGraph.setadjMetrix(adjMatrix) allPaths = mydeepGraph.getPathofTwoNode( 0, len(entryPointToethNode) - 1) allPaths_Node = allPaths_intToNode(allPaths, entryPointToethNode) for path in allPaths_Node[:]: careifNodeStack = [] care_if_StateVariablesRead = set() care_RequireOrAssert_StateVariableRead = set() state_variables_written = set() for node in path: # [start, end] # 直接转帐函数cfg上的路径节点 if node.contains_require_or_assert(): care_RequireOrAssert_StateVariableRead |= set( node.state_variables_read) state_variables_written |= set( node.state_variables_written) if node.type == NodeType.IF: for son in node.sons: if son.type == NodeType.THROW or son.type == NodeType.RETURN: careifNodeStack.append(node) if node.type == NodeType.IF: careifNodeStack.append(node) if node.type == NodeType.ENDIF: if careifNodeStack: careifNodeStack.pop() if careifNodeStack: # eth被包裹在if中 for careifNode in careifNodeStack: care_if_StateVariablesRead |= set( careifNode.state_variables_read) for stateVariableWritten in state_variables_written: for careStateVariableRead in care_if_StateVariablesRead | care_RequireOrAssert_StateVariableRead: result = is_dependent(stateVariableWritten, careStateVariableRead, function.contract) if result == True: return True # allPaths_Node.remove(path) else: # 如果 转账语句不在if block中 for stateVariableWritten in state_variables_written: for careStateVariableRead in care_RequireOrAssert_StateVariableRead: result = is_dependent(stateVariableWritten, careStateVariableRead, function.contract) if result == True: return True #allPaths_Node.remove(path) #return False # if allPaths_Node: # return False return False
def _have_reentrancy(self, function, eth_node_list, taint_node_list, private_visibility, have_public_caller, icfg=None): reentrancy_flag = False for taint_node in taint_node_list: ''' start_to_end = [start, ... ,end] ''' entry_node_to_taint = [] entry_node_to_taint.append(function.entry_point) if icfg is None: entry_node_to_taint.extend( list( set(function.nodes) - set([function.entry_point, taint_node]))) else: entry_node_to_taint.extend( list( set(icfg.allNodes) - set([function.entry_point, taint_node]))) entry_node_to_taint.append(taint_node) if icfg is None: adj_matrix = getadjMatrix(entry_node_to_taint) else: adj_matrix = getICFGadjMatrix(entry_node_to_taint) my_deep_graph = MyDeepGraph(len(entry_node_to_taint)) my_deep_graph.setadjMetrix(adj_matrix) all_path = my_deep_graph.getPathofTwoNode( 0, len(entry_node_to_taint) - 1) all_path_node = allPaths_intToNode(all_path, entry_node_to_taint) candidate_all_path_node = [] for path in all_path_node: if any(inode in eth_node_list for inode in path): candidate_all_path_node.append(path) if candidate_all_path_node: # 证明找到Reentrancy了,准备human look, 注意reversed, DM ''' 转变成普通人能看懂的形式,注意reversed ''' human_candidate_all_path_node = self.get_human_candidate_all_path_node( candidate_all_path_node) advance_update_flag = False # dm.advancedUpdateEth(function) txt1 = '\t\tcontract: {} | function: {} | private: {} | publicCaller: {} | Execution Locks and Eth ' \ 'money balance modification: {} ' txt2 = '\t\tcontract: {} | function: {} | private: {} | Execution Locks and Eth money balance ' \ 'modification: {} ' txt3 = '\t\t\tpath: {}' if private_visibility is True: if have_public_caller is True: reentrancy_flag = True print( txt1.format(function.contract.name, function.full_name, private_visibility, have_public_caller, advance_update_flag)) for human_candidate_path_node in human_candidate_all_path_node: print(txt3.format(human_candidate_path_node)) else: reentrancy_flag = True print( txt2.format(function.contract.name, function.full_name, private_visibility, advance_update_flag)) for human_candidate_path_node in human_candidate_all_path_node: print(txt3.format(human_candidate_path_node)) if reentrancy_flag is True: if icfg is None: txt = '[cfg_Reentrancy in] contract: {} . function: {} | {}' else: txt = '[icfg_Reentrancy in] contract: {} . function: {} | {}' print( txt.format(function.contract.name, function.full_name, function.source_mapping_str)) return reentrancy_flag
def advancedUpdateEth(self, function): # PPT,检查程序执行锁 from slither.analyses.data_dependency.data_dependency import is_dependent allNodes = function.nodes path_between_sender_and_if = [] for ethNode in function.ethNodes: entryPointToethNode = [] entryPointToethNode.append(function.entry_point) pilotProcessNodes = list( set(allNodes) - set([function.entry_point, ethNode])) entryPointToethNode.extend(pilotProcessNodes) entryPointToethNode.append(ethNode) adjMatrix = getadjMatrix(entryPointToethNode) mydeepGraph = MyDeepGraph(len(entryPointToethNode)) mydeepGraph.setadjMetrix(adjMatrix) allPaths = mydeepGraph.getPathofTwoNode( 0, len(entryPointToethNode) - 1) allPaths_Node = allPaths_intToNode(allPaths, entryPointToethNode) for path in allPaths_Node[:]: careifNodeStack = [] care_if_StateVariablesRead = set() care_RequireOrAssert_StateVariableRead = set() state_variables_written = set() for node in path: # [start, end] # 直接转帐函数cfg上的路径节点 if node.contains_require_or_assert(): care_RequireOrAssert_StateVariableRead |= set( node.state_variables_read) state_variables_written |= set( node.state_variables_written) if node.type == NodeType.IF: for son in node.sons: if son.type == NodeType.THROW or son.type == NodeType.RETURN: careifNodeStack.append(node) if node.type == NodeType.IF: careifNodeStack.append(node) path_between_sender_and_if.append(node) if node.type == NodeType.ENDIF: if careifNodeStack: careifNodeStack.pop() path_between_sender_and_if = [] else: path_between_sender_and_if.append(node) if careifNodeStack: # 被包裹在if语句中的Node for careifNode in careifNodeStack: care_if_StateVariablesRead |= set( careifNode.state_variables_read) for stateVariableWritten in state_variables_written: if len(care_if_StateVariablesRead | care_RequireOrAssert_StateVariableRead) > 1: return True if len(care_if_StateVariablesRead | care_RequireOrAssert_StateVariableRead) == 0: return True careStateVariableRead = list( care_if_StateVariablesRead | care_RequireOrAssert_StateVariableRead)[0] for suspicious_node in path_between_sender_and_if: ir_list = suspicious_node.irs_ssa for ir in ir_list: if isinstance(ir, Assignment): if hasattr(ir.lvalue, 'pure_name'): if ir.lvalue.pure_name == careStateVariableRead.name: r_v = ir.rvalue else: if ir.lvalue.name == careStateVariableRead.name: r_v = ir.rvalue else: r_v = None continue var_list_length = len( care_if_StateVariablesRead | care_RequireOrAssert_StateVariableRead) for careifNode in careifNodeStack: symbol_result = solve_expression( careifNode.irs_ssa, r_v) if symbol_result == False: return True else: result = is_dependent(stateVariableWritten, careStateVariableRead, function.contract) if result == True: return True # TODO: 为什么这个位置是True # allPaths_Node.remove(path) else: # 如果 转账语句不在if block中 for stateVariableWritten in state_variables_written: for careStateVariableRead in care_RequireOrAssert_StateVariableRead: result = is_dependent(stateVariableWritten, careStateVariableRead, function.contract) if result == True: return True #allPaths_Node.remove(path) #return False # if allPaths_Node: # return False return False