示例#1
0
文件: ssa.py 项目: gyDBD/slither
 def get(variable):
     if isinstance(variable, LocalVariable):
         if variable.name in local_variables_instances:
             return local_variables_instances[variable.name]
         new_var = LocalIRVariable(variable)
         local_variables_instances[variable.name] = new_var
         all_local_variables_instances[variable.name] = new_var
         return new_var
     if isinstance(
             variable, StateVariable
     ) and variable.canonical_name in state_variables_instances:
         return state_variables_instances[variable.canonical_name]
     elif isinstance(variable, ReferenceVariable):
         if not variable.index in reference_variables_instances:
             new_variable = ReferenceVariable(variable.node,
                                              index=variable.index)
             if variable.points_to:
                 new_variable.points_to = get(variable.points_to)
             new_variable.set_type(variable.type)
             reference_variables_instances[variable.index] = new_variable
         return reference_variables_instances[variable.index]
     elif isinstance(variable, TemporaryVariable):
         if not variable.index in temporary_variables_instances:
             new_variable = TemporaryVariable(variable.node,
                                              index=variable.index)
             new_variable.set_type(variable.type)
             temporary_variables_instances[variable.index] = new_variable
         return temporary_variables_instances[variable.index]
     return variable
示例#2
0
 def _post_member_access(self, expression):
     expr = get(expression.expression)
     val = ReferenceVariable(self._node)
     member = Member(expr, Constant(expression.member_name), val)
     member.set_expression(expression)
     self._result.append(member)
     set_val(expression, val)
示例#3
0
 def _post_index_access(self, expression):
     left = get(expression.expression_left)
     right = get(expression.expression_right)
     # Left can be a type for abi.decode(var, uint[2])
     if isinstance(left, Type):
         # Nested type are not yet supported by abi.decode, so the assumption
         # Is that the right variable must be a constant
         assert isinstance(right, Constant)
         t = ArrayType(left, right.value)
         set_val(expression, t)
         return
     val = ReferenceVariable(self._node)
     # access to anonymous array
     # such as [0,1][x]
     if isinstance(left, list):
         init_array_val = TemporaryVariable(self._node)
         init_array_right = left
         left = init_array_val
         operation = InitArray(init_array_right, init_array_val)
         operation.set_expression(expression)
         self._result.append(operation)
     operation = Index(val, left, right, expression.type)
     operation.set_expression(expression)
     self._result.append(operation)
     set_val(expression, val)
示例#4
0
 def _post_index_access(self, expression):
     left = get(expression.expression_left)
     right = get(expression.expression_right)
     val = ReferenceVariable(self._node)
     operation = Index(val, left, right, expression.type)
     self._result.append(operation)
     set_val(expression, val)
示例#5
0
    def _post_member_access(self, expression):
        expr = get(expression.expression)

        # Look for type(X).max / min
        # Because we looked at the AST structure, we need to look into the nested expression
        # Hopefully this is always on a direct sub field, and there is no weird construction
        if isinstance(expression.expression, CallExpression) and expression.member_name in [
            "min",
            "max",
        ]:
            if isinstance(expression.expression.called, Identifier):
                if expression.expression.called.value == SolidityFunction("type()"):
                    assert len(expression.expression.arguments) == 1
                    val = TemporaryVariable(self._node)
                    type_expression_found = expression.expression.arguments[0]
                    assert isinstance(type_expression_found, ElementaryTypeNameExpression)
                    type_found = type_expression_found.type
                    if expression.member_name == "min:":
                        op = Assignment(val, Constant(str(type_found.min), type_found), type_found,)
                    else:
                        op = Assignment(val, Constant(str(type_found.max), type_found), type_found,)
                    self._result.append(op)
                    set_val(expression, val)
                    return

        val = ReferenceVariable(self._node)
        member = Member(expr, Constant(expression.member_name), val)
        member.set_expression(expression)
        self._result.append(member)
        set_val(expression, val)
示例#6
0
 def _post_index_access(self, expression):
     left = get(expression.expression_left)
     right = get(expression.expression_right)
     val = ReferenceVariable(self._node)
     # access to anonymous array
     # such as [0,1][x]
     if isinstance(left, list):
         init_array_val = TemporaryVariable(self._node)
         init_array_right = left
         left = init_array_val
         operation = InitArray(init_array_right, init_array_val)
         self._result.append(operation)
     operation = Index(val, left, right, expression.type)
     self._result.append(operation)
     set_val(expression, val)
示例#7
0
    def _post_call_expression(self, expression):
        called = get(expression.called)
        args = [get(a) for a in expression.arguments if a]
        for arg in args:
            arg_ = Argument(arg)
            arg_.set_expression(expression)
            self._result.append(arg_)
        if isinstance(called, Function):
            # internal call

            # If tuple
            if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()':
                val = TupleVariable(self._node)
            else:
                val = TemporaryVariable(self._node)
            internal_call = InternalCall(called, len(args), val, expression.type_call)
            internal_call.set_expression(expression)
            self._result.append(internal_call)
            set_val(expression, val)
        else:
            # yul things
            if called.name == 'caller()':
                val = TemporaryVariable(self._node)
                var = Assignment(val, SolidityVariableComposed('msg.sender'), 'uint256')
                self._result.append(var)
                set_val(expression, val)
            elif called.name == 'origin()':
                val = TemporaryVariable(self._node)
                var = Assignment(val, SolidityVariableComposed('tx.origin'), 'uint256')
                self._result.append(var)
                set_val(expression, val)
            elif called.name == 'extcodesize(uint256)':
                val = ReferenceVariable(self._node)
                var = Member(args[0], Constant('codesize'), val)
                self._result.append(var)
                set_val(expression, val)
            elif called.name == 'selfbalance()':
                val = TemporaryVariable(self._node)
                var = TypeConversion(val, SolidityVariable('this'), ElementaryType('address'))
                self._result.append(var)

                val1 = ReferenceVariable(self._node)
                var1 = Member(val, Constant('balance'), val1)
                self._result.append(var1)
                set_val(expression, val1)
            elif called.name == 'address()':
                val = TemporaryVariable(self._node)
                var = TypeConversion(val, SolidityVariable('this'), ElementaryType('address'))
                self._result.append(var)
                set_val(expression, val)
            elif called.name == 'callvalue()':
                val = TemporaryVariable(self._node)
                var = Assignment(val, SolidityVariableComposed('msg.value'), 'uint256')
                self._result.append(var)
                set_val(expression, val)
            else:
                # If tuple
                if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()':
                    val = TupleVariable(self._node)
                else:
                    val = TemporaryVariable(self._node)

                message_call = TmpCall(called, len(args), val, expression.type_call)
                message_call.set_expression(expression)
                # Gas/value are only accessible here if the syntax {gas: , value: }
                # Is used over .gas().value()
                if expression.call_gas:
                    call_gas = get(expression.call_gas)
                    message_call.call_gas = call_gas
                if expression.call_value:
                    call_value = get(expression.call_value)
                    message_call.call_value = call_value
                if expression.call_salt:
                    call_salt = get(expression.call_salt)
                    message_call.call_salt = call_salt
                self._result.append(message_call)
                set_val(expression, val)
示例#8
0
文件: convert.py 项目: sreev/slither
def convert_to_pop(ir, node):
    """
    Convert pop operators
    Return a list of 6 operations
    """

    ret = []

    arr = ir.destination
    length = ReferenceVariable(node)
    length.set_type(ElementaryType('uint256'))

    ir_length = Length(arr, length)
    ir_length.set_expression(ir.expression)
    ir_length.set_node(ir.node)
    ir_length.lvalue.points_to = arr
    ret.append(ir_length)

    val = TemporaryVariable(node)

    ir_sub_1 = Binary(val, length, Constant("1", ElementaryType('uint256')), BinaryType.SUBTRACTION)
    ir_sub_1.set_expression(ir.expression)
    ir_sub_1.set_node(ir.node)
    ret.append(ir_sub_1)

    element_to_delete = ReferenceVariable(node)
    ir_assign_element_to_delete = Index(element_to_delete, arr, val, ElementaryType('uint256'))
    ir_length.lvalue.points_to = arr
    element_to_delete.set_type(ElementaryType('uint256'))
    ir_assign_element_to_delete.set_expression(ir.expression)
    ir_assign_element_to_delete.set_node(ir.node)
    ret.append(ir_assign_element_to_delete)

    ir_delete = Delete(element_to_delete, element_to_delete)
    ir_delete.set_expression(ir.expression)
    ir_delete.set_node(ir.node)
    ret.append(ir_delete)

    length_to_assign = ReferenceVariable(node)
    length_to_assign.set_type(ElementaryType('uint256'))
    ir_length = Length(arr, length_to_assign)
    ir_length.set_expression(ir.expression)
    ir_length.lvalue.points_to = arr
    ir_length.set_node(ir.node)
    ret.append(ir_length)

    ir_assign_length = Assignment(length_to_assign, val, ElementaryType('uint256'))
    ir_assign_length.set_expression(ir.expression)
    ir_assign_length.set_node(ir.node)
    ret.append(ir_assign_length)

    return ret
    def _post_call_expression(self, expression):  # pylint: disable=too-many-branches,too-many-statements
        called = get(expression.called)
        args = [get(a) for a in expression.arguments if a]
        for arg in args:
            arg_ = Argument(arg)
            arg_.set_expression(expression)
            self._result.append(arg_)
        if isinstance(called, Function):
            # internal call

            # If tuple
            if expression.type_call.startswith(
                    "tuple(") and expression.type_call != "tuple()":
                val = TupleVariable(self._node)
            else:
                val = TemporaryVariable(self._node)
            internal_call = InternalCall(called, len(args), val,
                                         expression.type_call)
            internal_call.set_expression(expression)
            self._result.append(internal_call)
            set_val(expression, val)
        else:
            # yul things
            if called.name == "caller()":
                val = TemporaryVariable(self._node)
                var = Assignment(val, SolidityVariableComposed("msg.sender"),
                                 "uint256")
                self._result.append(var)
                set_val(expression, val)
            elif called.name == "origin()":
                val = TemporaryVariable(self._node)
                var = Assignment(val, SolidityVariableComposed("tx.origin"),
                                 "uint256")
                self._result.append(var)
                set_val(expression, val)
            elif called.name == "extcodesize(uint256)":
                val = ReferenceVariable(self._node)
                var = Member(args[0], Constant("codesize"), val)
                self._result.append(var)
                set_val(expression, val)
            elif called.name == "selfbalance()":
                val = TemporaryVariable(self._node)
                var = TypeConversion(val, SolidityVariable("this"),
                                     ElementaryType("address"))
                self._result.append(var)

                val1 = ReferenceVariable(self._node)
                var1 = Member(val, Constant("balance"), val1)
                self._result.append(var1)
                set_val(expression, val1)
            elif called.name == "address()":
                val = TemporaryVariable(self._node)
                var = TypeConversion(val, SolidityVariable("this"),
                                     ElementaryType("address"))
                self._result.append(var)
                set_val(expression, val)
            elif called.name == "callvalue()":
                val = TemporaryVariable(self._node)
                var = Assignment(val, SolidityVariableComposed("msg.value"),
                                 "uint256")
                self._result.append(var)
                set_val(expression, val)
            else:
                # If tuple
                if expression.type_call.startswith(
                        "tuple(") and expression.type_call != "tuple()":
                    val = TupleVariable(self._node)
                else:
                    val = TemporaryVariable(self._node)

                message_call = TmpCall(called, len(args), val,
                                       expression.type_call)
                message_call.set_expression(expression)
                # Gas/value are only accessible here if the syntax {gas: , value: }
                # Is used over .gas().value()
                if expression.call_gas:
                    call_gas = get(expression.call_gas)
                    message_call.call_gas = call_gas
                if expression.call_value:
                    call_value = get(expression.call_value)
                    message_call.call_value = call_value
                if expression.call_salt:
                    call_salt = get(expression.call_salt)
                    message_call.call_salt = call_salt
                self._result.append(message_call)
                set_val(expression, val)
    def _post_member_access(self, expression):
        expr = get(expression.expression)

        # Look for type(X).max / min
        # Because we looked at the AST structure, we need to look into the nested expression
        # Hopefully this is always on a direct sub field, and there is no weird construction
        if isinstance(expression.expression,
                      CallExpression) and expression.member_name in [
                          "min",
                          "max",
                      ]:
            if isinstance(expression.expression.called, Identifier):
                if expression.expression.called.value == SolidityFunction(
                        "type()"):
                    assert len(expression.expression.arguments) == 1
                    val = TemporaryVariable(self._node)
                    type_expression_found = expression.expression.arguments[0]
                    assert isinstance(type_expression_found,
                                      ElementaryTypeNameExpression)
                    type_found = type_expression_found.type
                    if expression.member_name == "min:":
                        op = Assignment(
                            val,
                            Constant(str(type_found.min), type_found),
                            type_found,
                        )
                    else:
                        op = Assignment(
                            val,
                            Constant(str(type_found.max), type_found),
                            type_found,
                        )
                    self._result.append(op)
                    set_val(expression, val)
                    return

        # This does not support solidity 0.4 contract_name.balance
        if (isinstance(expr, Variable)
                and expr.type == ElementaryType("address")
                and expression.member_name in ["balance", "code", "codehash"]):
            val = TemporaryVariable(self._node)
            name = expression.member_name + "(address)"
            sol_func = SolidityFunction(name)
            s = SolidityCall(
                sol_func,
                1,
                val,
                sol_func.return_type,
            )
            s.set_expression(expression)
            s.arguments.append(expr)
            self._result.append(s)
            set_val(expression, val)
            return

        if isinstance(expr, TypeAlias) and expression.member_name in [
                "wrap", "unwrap"
        ]:
            # The logic is be handled by _post_call_expression
            set_val(expression, expr)
            return

        # Early lookup to detect user defined types from other contracts definitions
        # contract A { type MyInt is int}
        # contract B { function f() public{ A.MyInt test = A.MyInt.wrap(1);}}
        # The logic is handled by _post_call_expression
        if isinstance(expr, Contract):
            if expression.member_name in expr.file_scope.user_defined_types:
                set_val(
                    expression,
                    expr.file_scope.user_defined_types[expression.member_name])
                return

        val = ReferenceVariable(self._node)
        member = Member(expr, Constant(expression.member_name), val)
        member.set_expression(expression)
        self._result.append(member)
        set_val(expression, val)