From 7da40757bd61d7c44c5344b6f0c2f07c22fe608d Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Mon, 1 Oct 2018 22:40:58 -0700 Subject: [PATCH 1/2] Improve exception handling Changed all Exception objects raised to more specific classes implemented in pyevmasm. Additionally, disassemble_all now catches a ParseError exception that could be thrown by Instruction.parse_operand, which would cause the generator to raise an exception instead of returning None. --- pyevmasm/evmasm.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/pyevmasm/evmasm.py b/pyevmasm/evmasm.py index db42aff..42466da 100644 --- a/pyevmasm/evmasm.py +++ b/pyevmasm/evmasm.py @@ -35,6 +35,12 @@ class UnknownMnemonicError(Exception): class UnknownOpcodeError(Exception): pass +class AssembleError(Exception): + pass + +class ParseError(Exception): + pass + class InstructionTable(dict): """ @@ -365,7 +371,7 @@ def parse_operand(self, buf): operand |= next(buf) self._operand = operand except StopIteration: - raise Exception("Not enough data for decoding") + raise ParseError("Not enough data for decoding") @property def operand_size(self): @@ -557,8 +563,8 @@ def assemble_one(asmcode, pc=0): assert len(asmcode) == 2 instr.operand = int(asmcode[1], 0) return instr - except BaseException: - raise Exception("Something wrong at pc %d" % pc) + except: + raise AssembleError("Something wrong at pc %d" % pc) def assemble_all(asmcode, pc=0): @@ -627,10 +633,13 @@ def disassemble_one(bytecode, pc=0): instruction = instruction_table[opcode] instruction.pc = pc - if instruction.has_operand: - instruction.parse_operand(bytecode) - - return instruction + try: + if instruction.has_operand: + instruction.parse_operand(bytecode) + except ParseError: + instruction = None + finally: + return instruction def disassemble_all(bytecode, pc=0): From 49a118ef089d4d23f405408c1821ed594e15ae69 Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Mon, 1 Oct 2018 22:50:09 -0700 Subject: [PATCH 2/2] Make the `return` in `disassemble_all` explicit Rather than just a `return` statement, `StopIteration` makes it clearer that the generator is done. They're functionally equivalent, but it's better for clarity in my opinion. --- pyevmasm/evmasm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyevmasm/evmasm.py b/pyevmasm/evmasm.py index 42466da..7826da3 100644 --- a/pyevmasm/evmasm.py +++ b/pyevmasm/evmasm.py @@ -681,7 +681,7 @@ def disassemble_all(bytecode, pc=0): while True: instr = disassemble_one(bytecode, pc=pc) if not instr: - return + raise StopIteration pc += instr.size yield instr