コード例 #1
0
def eval_bool(exp, known_true = True, symbolic=True):

    if exp == known_true:
        return True

    if is_zero(exp) == known_true:
        return False

    if exp == is_zero(known_true):
        return False

    if type(exp) == int:
        return exp > 0

    if exp in (True, False):
        return True


    if opcode(exp) == 'bool':
        return eval_bool(exp[1], known_true=known_true, symbolic=symbolic)


    if opcode(exp) == 'iszero':
        e = eval_bool(exp[1], known_true=known_true, symbolic=symbolic)
        if e != None:
            return not e


    if opcode(exp) == 'or':
        res = 0
        for e in exp[1:]:
            ev = eval_bool(e, known_true=known_true, symbolic=symbolic)
            if type(ev) != None:
                res = res or ev
            else:
                return None

        return res

        #'ge', 'gt', 'eq' - tbd
    if opcode(exp) in ['le', 'lt'] and \
       opcode(exp) == opcode(known_true):
          if exp[1] == known_true[1]:
            # ('le', x, sth) while ('le', x, sth2) is known to be true
            if eval_bool((opcode(exp), known_true[2], exp[2])) is True:
                return True

    if not symbolic:
        r = eval(exp)
        if type(r) == int:
            return r != 0
        else:
            return None


    if opcode(exp) == 'le':
        left = eval(exp[1])
        right = eval(exp[2])

        if left == right:
            return True

        if type(left) == int and type(right) == int:
            return left <= right
        try:
            return algebra.le_op(left, right)
        except:
            return None


    if opcode(exp) == 'lt':
        left = eval(exp[1])
        right = eval(exp[2])

        if left == right:
            return False

        if type(left) == int and type(right) == int:
            return left < right

        try:
            return algebra.lt_op(left, right)
        except:
            return None


    if opcode(exp) == 'gt':
        left = eval(exp[1])
        right = eval(exp[2])

        if type(left) == int and type(right) == int:
            return left > right

        if left == right:
            return False
        else:
#            return None
            try:  #a > b iff b < a iff b+1 <= a
                le = algebra.lt_op(add_op(left, 1), right,1)
                logger.debug('le %s %s %s', le, left, right)

                if le == True:
                    return False
                if le == False:
                    return True
                if le is None:
                    return None
            except:
                pass

    if opcode(exp) == 'ge':
        left = eval(exp[1])
        right = eval(exp[2])

        if type(left) == int and type(right) == int:
            return left >= right

        if left == right:
            return True
        else:
            try:
                lt = algebra.lt_op(left, right)
                if lt == True:
                    return False
                if lt == False:
                    return True
                if lt is None:
                    return None
            except:
                pass


    if opcode(exp) == 'eq':
        left = eval(exp[1])
        right = eval(exp[2])

        if left == right:
            return True

        if algebra.sub_op(left, right) == 0:
            return True

    aeval = eval(exp)

    return None
コード例 #2
0
    def handle_call(self, op, trace):
        stack = self.stack

        gas = stack.pop()
        addr = stack.pop()
        if op == "call":
            wei = stack.pop()
        else:
            assert op == "staticcall"
            wei = 0

        arg_start = stack.pop()
        arg_len = stack.pop()
        ret_start = stack.pop()
        ret_len = stack.pop()

        if addr == 4:  # Identity

            m = mem_load(arg_start, arg_len)
            trace(("setmem", ("range", ret_start, arg_len), m))

            stack.append("memcopy.success")

        elif type(addr) == int and addr in precompiled:

            m = mem_load(arg_start, arg_len)
            args = mem_load(arg_start, arg_len)
            var_name = precompiled_var_names[addr]

            trace(("precompiled", var_name, precompiled[addr], args))
            trace(("setmem", ("range", ret_start, ret_len), ("var", var_name)))

            stack.append("{}.result".format(precompiled[addr]))

        else:
            assert op in ("call", "staticcall")
            call_trace = (
                op,
                gas,
                addr,
                wei,
            )

            if arg_len == 0:
                call_trace += None, None

            elif arg_len == 4:

                call_trace += mem_load(arg_start, 4), None

            else:
                fname = mem_load(arg_start, 4)
                fparams = mem_load(add_op(arg_start, 4), sub_op(arg_len, 4))
                call_trace += fname, fparams

            trace(call_trace)
            #           trace(('comment', mem_load(arg_start, arg_len)))

            self.call_len = ret_len

            stack.append("ext_call.success")

            if lt_op(0, ret_len):
                return_data = ("ext_call.return_data", 0, ret_len)
                trace(("setmem", ("range", ret_start, ret_len), return_data))
コード例 #3
0
def eval_bool(exp, known_true=True, symbolic=True):
    if exp == known_true:
        return True

    if is_zero(exp) == known_true:
        return False

    if exp == is_zero(known_true):
        return False

    if type(exp) == int:
        return exp > 0

    if exp in (True, False):
        return True

    if opcode(exp) == "bool":
        return eval_bool(exp[1], known_true=known_true, symbolic=symbolic)

    if opcode(exp) == "iszero":
        e = eval_bool(exp[1], known_true=known_true, symbolic=symbolic)
        if e is not None:
            return not e

    if opcode(exp) == "or":
        res = 0
        for e in exp[1:]:
            ev = eval_bool(e, known_true=known_true, symbolic=symbolic)
            if ev is None:
                return None
            res = res or ev
        return res

        #'ge', 'gt', 'eq' - tbd
    if opcode(exp) in ["le", "lt"] and opcode(exp) == opcode(known_true):
        if exp[1] == known_true[1]:
            # ('le', x, sth) while ('le', x, sth2) is known to be true
            if eval_bool((opcode(exp), known_true[2], exp[2])) is True:
                return True

    if not symbolic:
        r = eval(exp)

        if type(r) == int:
            return r != 0

        return None

    if opcode(exp) == "le":
        left = eval(exp[1])
        right = eval(exp[2])

        if left == right:
            return True

        if type(left) == int and type(right) == int:
            return left <= right

        try:
            return algebra.le_op(left, right)
        except Exception:
            return None

    if opcode(exp) == "lt":
        left = eval(exp[1])
        right = eval(exp[2])

        if left == right:
            return False

        if type(left) == int and type(right) == int:
            return left < right

        try:
            return algebra.lt_op(left, right)
        except Exception:
            return None

    if opcode(exp) == "gt":
        left = eval(exp[1])
        right = eval(exp[2])

        if type(left) == int and type(right) == int:
            return left > right

        if left == right:
            return False

        try:  # a > b iff b < a iff b+1 <= a
            le = algebra.lt_op(algebra.add_op(left, 1), right, 1)
            logger.debug("le %s %s %s", le, left, right)

            if le == True:
                return False
            if le == False:
                return True
            if le is None:
                return None
        except Exception:
            pass

    if opcode(exp) == "ge":
        left = eval(exp[1])
        right = eval(exp[2])

        if type(left) == int and type(right) == int:
            return left >= right

        if left == right:
            return True

        try:
            lt = algebra.lt_op(left, right)
            if lt == True:
                return False
            if lt == False:
                return True
            if lt is None:
                return None
        except Exception:
            pass

    if opcode(exp) == "eq":
        left = eval(exp[1])
        right = eval(exp[2])

        if left == right:
            return True

        if algebra.sub_op(left, right) == 0:
            return True

    return None