From 25ad20d9c3070ad998486efd5d12ad26199b6908 Mon Sep 17 00:00:00 2001 From: feliam Date: Sat, 29 Sep 2018 10:51:53 -0300 Subject: [PATCH 1/3] Add an option to make disassembly more forgiving --- pyevmasm/evmasm.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/pyevmasm/evmasm.py b/pyevmasm/evmasm.py index db42aff..672ae0a 100644 --- a/pyevmasm/evmasm.py +++ b/pyevmasm/evmasm.py @@ -596,13 +596,15 @@ def assemble_all(asmcode, pc=0): pc += instr.size -def disassemble_one(bytecode, pc=0): +def disassemble_one(bytecode, pc=0, silent=False): """ Disassemble a single instruction from a bytecode :param bytecode: the bytecode stream :type bytecode: str | bytes | bytearray | iterator :param pc: program counter of the instruction(optional) :type pc: int + :param silent: if True disassemble unrecognized instructions as INVALID or incomplete intruction operands as zero + :type silent: bool :return: an Instruction object :rtype: Instruction @@ -624,22 +626,32 @@ def disassemble_one(bytecode, pc=0): assert isinstance(opcode, int) - instruction = instruction_table[opcode] + + if silent: + if opcode not in instruction_table: + instruction = copy(instruction_table[opcode]) + instruction = copy(instruction_table[opcode]) instruction.pc = pc + if silent: + from itertools import chain, repeat + bytecode = chain(bytecode, repeat(0)) + if instruction.has_operand: instruction.parse_operand(bytecode) return instruction -def disassemble_all(bytecode, pc=0): +def disassemble_all(bytecode, pc=0, silent=False): """ Disassemble all instructions in bytecode :param bytecode: an evm bytecode (binary) :type bytecode: str | bytes | bytearray | iterator :param pc: program counter of the first instruction(optional) :type pc: int + :param silent: if True disassemble unrecognized instructions as INVALID or incomplete intruction operands as zero + :type silent: bool :return: An generator of Instruction objects :rtype: list[Instruction] @@ -670,19 +682,21 @@ def disassemble_all(bytecode, pc=0): bytecode = iter(bytecode) while True: - instr = disassemble_one(bytecode, pc=pc) + instr = disassemble_one(bytecode, pc=pc, silent=silent) if not instr: return pc += instr.size yield instr -def disassemble(bytecode, pc=0): +def disassemble(bytecode, pc=0, silent=False): """ Disassemble an EVM bytecode :param bytecode: binary representation of an evm bytecode :type bytecode: str | bytes | bytearray :param pc: program counter of the first instruction(optional) + :param silent: if True disassemble unrecognized instructions as INVALID or incomplete intruction operands as zero + :type silent: bool :type pc: int :return: the text representation of the assembler code @@ -697,7 +711,7 @@ def disassemble(bytecode, pc=0): PUSH2 0x100 """ - return '\n'.join(map(str, disassemble_all(bytecode, pc=pc))) + return '\n'.join(map(str, disassemble_all(bytecode, pc=pc, silent=silent))) def assemble(asmcode, pc=0): From fe8a8b817c3aaca8c1fe82a7e73a5a695ffa8816 Mon Sep 17 00:00:00 2001 From: feliam Date: Sat, 29 Sep 2018 10:55:57 -0300 Subject: [PATCH 2/3] Forgot import --- pyevmasm/evmasm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyevmasm/evmasm.py b/pyevmasm/evmasm.py index 672ae0a..67d3542 100644 --- a/pyevmasm/evmasm.py +++ b/pyevmasm/evmasm.py @@ -1,6 +1,7 @@ from binascii import hexlify, unhexlify from builtins import map, next, range, object from future.builtins import next, bytes +from copy imports copy """ Example use:: From 9f737ff48e9c6c5277a444df0aa8f04e9bd35264 Mon Sep 17 00:00:00 2001 From: feliam Date: Mon, 1 Oct 2018 18:26:35 -0300 Subject: [PATCH 3/3] Bugfix.. choose INVALID when undef --- pyevmasm/evmasm.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pyevmasm/evmasm.py b/pyevmasm/evmasm.py index 67d3542..ff50a4c 100644 --- a/pyevmasm/evmasm.py +++ b/pyevmasm/evmasm.py @@ -627,11 +627,14 @@ def disassemble_one(bytecode, pc=0, silent=False): assert isinstance(opcode, int) + try: + instruction = copy(instruction_table[opcode]) + except KeyError: + if silent: + instruction = copy(instruction_table[0xfe]) + else: + raise - if silent: - if opcode not in instruction_table: - instruction = copy(instruction_table[opcode]) - instruction = copy(instruction_table[opcode]) instruction.pc = pc if silent: