Пример #1
0
    def convert_expression_to_slithir(self):
        for func in self.functions + self.modifiers:
            try:
                func.generate_slithir_and_analyze()
            except AttributeError:
                # This can happens for example if there is a call to an interface
                # And the interface is redefined due to contract's name reuse
                # But the available version misses some functions
                self.log_incorrect_parsing(
                    f'Impossible to generate IR for {self.name}.{func.name}')

        all_ssa_state_variables_instances = dict()

        for contract in self.inheritance:
            for v in contract.state_variables_declared:
                new_var = StateIRVariable(v)
                all_ssa_state_variables_instances[v.canonical_name] = new_var
                self._initial_state_variables.append(new_var)

        for v in self.variables:
            if v.contract == self:
                new_var = StateIRVariable(v)
                all_ssa_state_variables_instances[v.canonical_name] = new_var
                self._initial_state_variables.append(new_var)

        for func in self.functions + self.modifiers:
            func.generate_slithir_ssa(all_ssa_state_variables_instances)
Пример #2
0
def update_lvalue(new_ir, node, local_variables_instances,
                  all_local_variables_instances, state_variables_instances,
                  all_state_variables_instances):
    if isinstance(new_ir, OperationWithLValue):
        lvalue = new_ir.lvalue
        update_through_ref = False
        if isinstance(new_ir, (Assignment, Binary)):
            if isinstance(lvalue, ReferenceVariable):
                update_through_ref = True
                while isinstance(lvalue, ReferenceVariable):
                    lvalue = lvalue.points_to
        if isinstance(lvalue, (LocalIRVariable, StateIRVariable)):
            if isinstance(lvalue, LocalIRVariable):
                new_var = LocalIRVariable(lvalue)
                new_var.index = all_local_variables_instances[
                    lvalue.name].index + 1
                all_local_variables_instances[lvalue.name] = new_var
                local_variables_instances[lvalue.name] = new_var
            else:
                new_var = StateIRVariable(lvalue)
                new_var.index = all_state_variables_instances[
                    lvalue.canonical_name].index + 1
                all_state_variables_instances[lvalue.canonical_name] = new_var
                state_variables_instances[lvalue.canonical_name] = new_var
            if update_through_ref:
                phi_operation = Phi(new_var, {node})
                phi_operation.rvalues = [lvalue]
                node.add_ssa_ir(phi_operation)
            if not isinstance(new_ir.lvalue, ReferenceVariable):
                new_ir.lvalue = new_var
            else:
                to_update = new_ir.lvalue
                while isinstance(to_update.points_to, ReferenceVariable):
                    to_update = to_update.points_to
                to_update.points_to = new_var
Пример #3
0
    def convert_expression_to_slithir(self):
        for func in self.functions + self.modifiers:
            func.generate_slithir_and_analyze()

        all_ssa_state_variables_instances = dict()

        for contract in self.inheritance:
            for v in contract.state_variables_declared:
                new_var = StateIRVariable(v)
                all_ssa_state_variables_instances[v.canonical_name] = new_var
                self._initial_state_variables.append(new_var)

        for v in self.variables:
            if v.contract == self:
                new_var = StateIRVariable(v)
                all_ssa_state_variables_instances[v.canonical_name] = new_var
                self._initial_state_variables.append(new_var)

        for func in self.functions + self.modifiers:
            func.generate_slithir_ssa(all_ssa_state_variables_instances)
Пример #4
0
    def convert_expression_to_slithir_ssa(self):
        """
        Assume generate_slithir_and_analyze was called on all functions

        :return:
        """
        from slither.slithir.variables import StateIRVariable

        all_ssa_state_variables_instances = dict()

        for contract in self.inheritance:
            for v in contract.state_variables_declared:
                new_var = StateIRVariable(v)
                all_ssa_state_variables_instances[v.canonical_name] = new_var
                self._initial_state_variables.append(new_var)

        for v in self.variables:
            if v.contract == self:
                new_var = StateIRVariable(v)
                all_ssa_state_variables_instances[v.canonical_name] = new_var
                self._initial_state_variables.append(new_var)

        for func in self.functions + self.modifiers:
            func.generate_slithir_ssa(all_ssa_state_variables_instances)
Пример #5
0
def add_ssa_ir(function, all_state_variables_instances):
    '''
        Add SSA version of the IR
    Args:
        function
        all_state_variables_instances
    '''

    if not function.is_implemented:
        return

    init_definition = dict()
    for v in function.parameters + function.returns:
        if v.name:
            init_definition[v.name] = (v, function.entry_point)

    # We only add phi function for state variable at entry node if
    # The state variable is used
    # And if the state variables is written in another function (otherwise its stay at index 0)
    for (_, variable_instance) in all_state_variables_instances.items():
        if is_used_later(function.entry_point, variable_instance):
            # rvalues are fixed in solc_parsing.declaration.function
            function.entry_point.add_ssa_ir(
                Phi(StateIRVariable(variable_instance), set()))

    add_phi_origins(function.entry_point, init_definition, dict())

    for node in function.nodes:
        for (variable, nodes) in node.phi_origins_local_variables.values():
            if len(nodes) < 2:
                continue
            if not is_used_later(node, variable):
                continue
            node.add_ssa_ir(Phi(LocalIRVariable(variable), nodes))
        for (variable, nodes) in node.phi_origins_state_variables.values():
            if len(nodes) < 2:
                continue
            #if not is_used_later(node, variable.name, []):
            #    continue
            node.add_ssa_ir(Phi(StateIRVariable(variable), nodes))

    init_local_variables_instances = dict()
    for v in function.parameters:
        if v.name:
            new_var = LocalIRVariable(v)
            function.add_parameter_ssa(new_var)
            if new_var.is_storage:
                fake_variable = LocalIRVariable(v)
                fake_variable.name = 'STORAGE_' + fake_variable.name
                fake_variable.set_location('reference_to_storage')
                new_var.refers_to = {fake_variable}
                init_local_variables_instances[
                    fake_variable.name] = fake_variable
            init_local_variables_instances[v.name] = new_var

    for v in function.returns:
        if v.name:
            new_var = LocalIRVariable(v)
            function.add_return_ssa(new_var)
            if new_var.is_storage:
                fake_variable = LocalIRVariable(v)
                fake_variable.name = 'STORAGE_' + fake_variable.name
                fake_variable.set_location('reference_to_storage')
                new_var.refers_to = {fake_variable}
                init_local_variables_instances[
                    fake_variable.name] = fake_variable
            init_local_variables_instances[v.name] = new_var

    all_init_local_variables_instances = dict(init_local_variables_instances)

    init_state_variables_instances = dict(all_state_variables_instances)

    initiate_all_local_variables_instances(function.nodes,
                                           init_local_variables_instances,
                                           all_init_local_variables_instances)

    generate_ssa_irs(function.entry_point,
                     dict(init_local_variables_instances),
                     all_init_local_variables_instances,
                     dict(init_state_variables_instances),
                     all_state_variables_instances,
                     init_local_variables_instances, [])

    fix_phi_rvalues_and_storage_ref(function.entry_point,
                                    dict(init_local_variables_instances),
                                    all_init_local_variables_instances,
                                    dict(init_state_variables_instances),
                                    all_state_variables_instances,
                                    init_local_variables_instances)
Пример #6
0
def generate_ssa_irs(node, local_variables_instances,
                     all_local_variables_instances, state_variables_instances,
                     all_state_variables_instances,
                     init_local_variables_instances, visited):

    if node in visited:
        return

    if node.type in [NodeType.ENDIF, NodeType.ENDLOOP] and any(
            not father in visited for father in node.fathers):
        return

    # visited is shared
    visited.append(node)

    for ir in node.irs_ssa:
        assert isinstance(ir, Phi)
        update_lvalue(ir, node, local_variables_instances,
                      all_local_variables_instances, state_variables_instances,
                      all_state_variables_instances)

    # these variables are lived only during the liveness of the block
    # They dont need phi function
    temporary_variables_instances = dict()
    reference_variables_instances = dict()

    for ir in node.irs:
        new_ir = copy_ir(ir, local_variables_instances,
                         state_variables_instances,
                         temporary_variables_instances,
                         reference_variables_instances,
                         all_local_variables_instances)

        update_lvalue(new_ir, node, local_variables_instances,
                      all_local_variables_instances, state_variables_instances,
                      all_state_variables_instances)

        if new_ir:

            node.add_ssa_ir(new_ir)

            if isinstance(ir, (InternalCall, HighLevelCall,
                               InternalDynamicCall, LowLevelCall)):
                if isinstance(ir, LibraryCall):
                    continue
                for variable in all_state_variables_instances.values():
                    if not is_used_later(node, variable):
                        continue
                    new_var = StateIRVariable(variable)
                    new_var.index = all_state_variables_instances[
                        variable.canonical_name].index + 1
                    all_state_variables_instances[
                        variable.canonical_name] = new_var
                    state_variables_instances[
                        variable.canonical_name] = new_var
                    phi_ir = PhiCallback(new_var, {node}, new_ir, variable)
                    # rvalues are fixed in solc_parsing.declaration.function
                    node.add_ssa_ir(phi_ir)

            if isinstance(new_ir, (Assignment, Binary)):
                if isinstance(new_ir.lvalue, LocalIRVariable):
                    if new_ir.lvalue.is_storage:
                        if isinstance(new_ir.rvalue, ReferenceVariable):
                            refers_to = new_ir.rvalue.points_to_origin
                            new_ir.lvalue.add_refers_to(refers_to)
                        else:
                            new_ir.lvalue.add_refers_to(new_ir.rvalue)

    for succ in node.dominator_successors:
        generate_ssa_irs(succ, dict(local_variables_instances),
                         all_local_variables_instances,
                         dict(state_variables_instances),
                         all_state_variables_instances,
                         init_local_variables_instances, visited)

    for dominated in node.dominance_frontier:
        generate_ssa_irs(dominated, dict(local_variables_instances),
                         all_local_variables_instances,
                         dict(state_variables_instances),
                         all_state_variables_instances,
                         init_local_variables_instances, visited)
Пример #7
0
def generate_ssa_irs(
    node,
    local_variables_instances,
    all_local_variables_instances,
    state_variables_instances,
    all_state_variables_instances,
    init_local_variables_instances,
    visited,
):

    if node in visited:
        return

    if node.type in [NodeType.ENDIF, NodeType.ENDLOOP] and any(
            not father in visited for father in node.fathers):
        return

    # visited is shared
    visited.append(node)

    for ir in node.irs_ssa:
        assert isinstance(ir, Phi)
        update_lvalue(
            ir,
            node,
            local_variables_instances,
            all_local_variables_instances,
            state_variables_instances,
            all_state_variables_instances,
        )

    # these variables are lived only during the liveness of the block
    # They dont need phi function
    temporary_variables_instances = {}
    reference_variables_instances = {}
    tuple_variables_instances = {}

    for ir in node.irs:
        new_ir = copy_ir(
            ir,
            local_variables_instances,
            state_variables_instances,
            temporary_variables_instances,
            reference_variables_instances,
            tuple_variables_instances,
            all_local_variables_instances,
        )

        new_ir.set_expression(ir.expression)
        new_ir.set_node(ir.node)

        update_lvalue(
            new_ir,
            node,
            local_variables_instances,
            all_local_variables_instances,
            state_variables_instances,
            all_state_variables_instances,
        )

        if new_ir:

            node.add_ssa_ir(new_ir)

            if isinstance(ir, (InternalCall, HighLevelCall,
                               InternalDynamicCall, LowLevelCall)):
                if isinstance(ir, LibraryCall):
                    continue
                for variable in all_state_variables_instances.values():
                    if not is_used_later(node, variable):
                        continue
                    new_var = StateIRVariable(variable)
                    new_var.index = all_state_variables_instances[
                        variable.canonical_name].index + 1
                    all_state_variables_instances[
                        variable.canonical_name] = new_var
                    state_variables_instances[
                        variable.canonical_name] = new_var
                    phi_ir = PhiCallback(new_var, {node}, new_ir, variable)
                    # rvalues are fixed in solc_parsing.declaration.function
                    node.add_ssa_ir(phi_ir)

            if isinstance(new_ir, (Assignment, Binary)):
                if isinstance(new_ir.lvalue, LocalIRVariable):
                    if new_ir.lvalue.is_storage:
                        if isinstance(new_ir.rvalue, ReferenceVariable):
                            refers_to = new_ir.rvalue.points_to_origin
                            new_ir.lvalue.add_refers_to(refers_to)
                        # Discard Constant
                        # This can happen on yul, like
                        # assembly { var.slot = some_value }
                        # Here we do not keep track of the references as we do not track
                        # such low level manipulation
                        # However we could extend our storage model to do so in the future
                        elif not isinstance(new_ir.rvalue, Constant):
                            new_ir.lvalue.add_refers_to(new_ir.rvalue)

    for succ in node.dominator_successors:
        generate_ssa_irs(
            succ,
            dict(local_variables_instances),
            all_local_variables_instances,
            dict(state_variables_instances),
            all_state_variables_instances,
            init_local_variables_instances,
            visited,
        )

    for dominated in node.dominance_frontier:
        generate_ssa_irs(
            dominated,
            dict(local_variables_instances),
            all_local_variables_instances,
            dict(state_variables_instances),
            all_state_variables_instances,
            init_local_variables_instances,
            visited,
        )