def _create_node( self, func: Function, counter: int, variable: "Variable", scope: Union[Scope, Function] ): from slither.core.cfg.node import Node, NodeType from slither.core.expressions import ( AssignmentOperationType, AssignmentOperation, Identifier, ) # Function uses to create node for state variable declaration statements node = Node(NodeType.OTHER_ENTRYPOINT, counter, scope) node.set_offset(variable.source_mapping, self.compilation_unit) node.set_function(func) func.add_node(node) assert variable.expression expression = AssignmentOperation( Identifier(variable), variable.expression, AssignmentOperationType.ASSIGN, variable.type, ) expression.set_offset(variable.source_mapping, self.compilation_unit) node.add_expression(expression) return node
def _parse_function(self, function_data: Dict): func = Function() func.set_offset(function_data["src"], self._contract.slither) func.set_contract(self._contract) func.set_contract_declarer(self._contract) func_parser = FunctionSolc(func, function_data, self) self._contract.slither.add_function(func) self._functions_no_params.append(func_parser) self._functions_parser.append(func_parser) self._slither_parser.add_functions_parser(func_parser)
def add_constructor_variables(self): if self.state_variables: for (idx, variable_candidate) in enumerate(self.state_variables): if variable_candidate.expression and not variable_candidate.is_constant: constructor_variable = Function() constructor_variable.set_function_type( FunctionType.CONSTRUCTOR_VARIABLES) constructor_variable.set_contract(self) constructor_variable.set_contract_declarer(self) constructor_variable.set_visibility("internal") # For now, source mapping of the constructor variable is the whole contract # Could be improved with a targeted source mapping constructor_variable.set_offset(self.source_mapping, self.slither) self._functions[constructor_variable. canonical_name] = constructor_variable prev_node = self._create_node(constructor_variable, 0, variable_candidate) variable_candidate.node_initialization = prev_node counter = 1 for v in self.state_variables[idx + 1:]: if v.expression and not v.is_constant: next_node = self._create_node( constructor_variable, counter, v) v.node_initialization = next_node prev_node.add_son(next_node) next_node.add_father(prev_node) prev_node = next_node counter += 1 break for (idx, variable_candidate) in enumerate(self.state_variables): if variable_candidate.expression and variable_candidate.is_constant: constructor_variable = Function() constructor_variable.set_function_type( FunctionType.CONSTRUCTOR_CONSTANT_VARIABLES) constructor_variable.set_contract(self) constructor_variable.set_contract_declarer(self) constructor_variable.set_visibility("internal") # For now, source mapping of the constructor variable is the whole contract # Could be improved with a targeted source mapping constructor_variable.set_offset(self.source_mapping, self.slither) self._functions[constructor_variable. canonical_name] = constructor_variable prev_node = self._create_node(constructor_variable, 0, variable_candidate) variable_candidate.node_initialization = prev_node counter = 1 for v in self.state_variables[idx + 1:]: if v.expression and v.is_constant: next_node = self._create_node( constructor_variable, counter, v) v.node_initialization = next_node prev_node.add_son(next_node) next_node.add_father(prev_node) prev_node = next_node counter += 1 break
def __init__(self, contract_info: ContractInfo, function: Function, test_mode=0, simple=0, rename=0): self.simple = simple # 简易流程 self.rename = rename # 变量名称混淆 self.test_mode = test_mode # 测试模式 self.contract_info = contract_info self.can_send_ether = function.can_send_eth() self.function = function self.fid = function.id self.name: str = function.name.__str__() self.visibility = function.visibility # 函数调用链: 上级函数链 [[chain1], [chain2], [chain3]] self.callee_chains = None # 语义相关 初始信息 self.input_params = {} # 入参列表 self.stmt_internal_call = {} # 当前语句是否调用函数 <node_id, fid> self.if_stmts = [] # 条件语句列表 self.vars_list = [] # 函数中使用的说有的变量列表 self.vars_map = {} # 函数中使用的说有的变量列表 self.stmts_var_info_maps = {} # 各语句变量使用情况 self.transaction_stmts = {} # 存在交易行为的语句列表 transaction_stmts self.loop_stmts = [] # 循环语句列表 self.if_paris = {} # IF 与 END_IF self.node_id_2_idx = {} # function.node.node_id -> node的idx function.nodes[idx] self.idx_2_node_id = {} # function.node.node_id <- node的idx function.nodes[idx] self.state_def_stmts = {} # 全局变量write(def)语句 self.const_var_init = {} # 涉及的全局变量初始化语句 self.msg_value_stmt = {} # 使用了msg.value的语句 # 交易全局变量,需要通过数据流分析器获取 self.transaction_states = None # <交易语句, [交易涉及的全部全局变量]> # 函数内调用分析, cfg节点为调用外部函数 self.intra_function_result_at_cfg = {} # 函数间:外部函数修改全局变量语句集合 self.external_state_def_nodes_map = None # 切片准则 self.criterias = None # 交易语句 self.criterias_msg = None # msg.value self.append_criterias = None # 交易相关全局变量,依赖数据流分析器 DataFlowAnalyzer self.external_criterias = None # 过程间分析依赖的切片准则 # 序列化表示:plain source code of function self.psc = [] # 图表示 self.cfg = None self.simple_cfg = None self.pdg = None # 切片后的图表示 # key1: 交易语句ID,也就是criteria,无外部全局变量写和常数初始化; # key2: - tag@交易语句ID_with_外部写函数: 构建函数调用图时加入的; # - 表明该切片准则数据依赖于某外部调用函数的返回值; self.sliced_pdg = {} # 不同的语义边 self.semantic_edges = {} # 初始化 self.function_info_analyze()