def load_binary(self, source): stack = [] self.binary = [] if source[:2] == "0x": source = source[2:] while len(source[:2]) > 0: num = int("0x" + source[:2], 16) self.binary.append(num) stack = [num] + stack source = source[2:] line = 0 parsed_lines = [] while len(stack) > 0: popped = stack.pop() orig_line = line if popped not in opcode_dict: op = "UNKNOWN" param = popped else: param = None op = opcode_dict[popped] if op == "jumpdest": self.jump_dests.append(line) if op[:4] == "push": num_words = int(op[4:]) param = 0 for i in range(num_words): try: param = param * 0x100 + stack.pop() line += 1 except Exception: break parsed_lines.append((orig_line, op, param)) line += 1 self.parsed_lines = parsed_lines self.last_line = line self.lines = {} for line_no, op, param in parsed_lines: if op[:4] == "push" and param > 1000000000000000: param = pretty_bignum( param) # convert big numbers into strings if possibble # should be moved to prettify really if op[:3] == "dup": param = int(op[3:]) op = "dup" if op[:4] == "swap": param = int(op[4:]) op = "swap" self.lines[line_no] = (line_no, op, param) return self.lines
def pretty_memory(exp, add_color=False): if exp is None: return tuple() if exp == 'mem': return prettify(exp, add_color=add_color) if opcode(exp) != 'data': return (prettify(exp, add_color=add_color), ) exp = exp[1:] if len(exp) == 0: return 'empty()' assert len(exp) > 0, exp res = [] idx = 0 def unmask(exp): if opcode(exp) == 'mask_shl': return exp[4] return exp # merge things that look like string into a string while idx < len(exp): if idx == 0 and type(exp[0]) == tuple and exp[0][:4] == ('mask_shl', 32, 224, 0) and type(exp[0][4]) == int: # This happens often in Log and Revert, first # memory result being an 8-byte identifier. # Definitely deserves a more generic solution. # # example: 0xd883209C4DCd497f24633C627a4E451013424841, sendFoods function v = exp[0][4] >> 224 res.append( pretty_fname(v, add_color) ) idx += 1 continue el = exp[idx] # detect a potential string out_str = None if unmask(el) == 32 and len(exp)>idx+1: length = unmask(exp[idx+1]) if type(length) == int: byte_length = ((length-1) >> 5) +1 out_str = '' if type(length) == int and len(exp) > idx + 1 + byte_length: for i in range(byte_length): if type(unmask(exp[idx+2+i])) == str: out_str += unmask(exp[idx+2+i])[1:-1] elif type(pretty_bignum(unmask(exp[idx+2+i]))) == str: # could also make sure that the length of string is the same # as expected out_str += pretty_bignum(unmask(exp[idx+2+i]))[1:-1] else: out_str = None break if out_str != None: idx = idx + 1 + byte_length else: out_str = None else: out_str = None if out_str != None: res.append("'"+out_str+"'") else: res.append(prettify(el, add_color=add_color, parentheses=False)) idx = idx+1 return tuple(res)