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
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))
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