Пример #1
0
    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
Пример #2
0
    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)
Пример #3
0
    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()