1- import collections
2-
3- class memoized (object ):
4- '''Decorator. Caches a function's return value each time it is called.
5- If called later with the same arguments, the cached value is returned
6- (not reevaluated).
7- '''
8-
9- def __init__ (self , func ):
10- self .func = func
11- self .cache = {}
12-
13- def __call__ (self , * args , ** kwargs ):
14- key = args + tuple (sorted (kwargs .items ()))
15- if not isinstance (key , collections .Hashable ):
16- # uncacheable. a list, for instance.
17- # better to not cache than blow up.
18- return self .func (* args , ** kwargs )
19- if key in self .cache :
20- return self .cache [key ]
21- else :
22- value = self .func (* args , ** kwargs )
23- self .cache [key ] = value
24- return value
25-
26- def __repr__ (self ):
27- '''Return the function's docstring.'''
28- return self .func .__doc__
29-
30- def __get__ (self , obj , objtype ):
31- '''Support instance methods.'''
32- return functools .partial (self .__call__ , obj )
1+ from builtins import map , next , chr , range , object
2+ from binascii import hexlify , unhexlify
3+ from .util import memoized
334
345
356class EVMAsm (object ):
@@ -38,7 +9,7 @@ class EVMAsm(object):
389
3910 Example use::
4011
41- >>> from manticore.platforms.evm import EVMAsm
12+ >>> from evmasm import EVMAsm
4213 >>> EVMAsm.disassemble_one('\\ x60\\ x10')
4314 Instruction(0x60, 'PUSH', 1, 0, 1, 0, 'Place 1 byte item on stack.', 16, 0)
4415 >>> EVMAsm.assemble_one('PUSH1 0x10')
@@ -221,7 +192,7 @@ def bytes(self):
221192 ''' Encoded instruction '''
222193 bytes = []
223194 bytes .append (chr (self ._opcode ))
224- for offset in reversed (xrange (self .operand_size )):
195+ for offset in reversed (range (self .operand_size )):
225196 c = (self .operand >> offset * 8 ) & 0xff
226197 bytes .append (chr (c ))
227198 return '' .join (bytes )
@@ -470,7 +441,7 @@ def is_arithmetic(self):
470441 def _get_reverse_table ():
471442 ''' Build an internal table used in the assembler '''
472443 reverse_table = {}
473- for (opcode , (name , immediate_operand_size , pops , pushes , gas , description )) in EVMAsm ._table .items ():
444+ for (opcode , (name , immediate_operand_size , pops , pushes , gas , description )) in list ( EVMAsm ._table .items () ):
474445 mnemonic = name
475446 if name == 'PUSH' :
476447 mnemonic = '%s%d' % (name , (opcode & 0x1f ) + 1 )
@@ -485,7 +456,7 @@ def assemble_one(assembler, pc=0):
485456 ''' Assemble one EVM instruction from its textual representation.
486457
487458 :param assembler: assembler code for one instruction
488- :param pc: program counter of the instruction (optional)
459+ :param pc: program counter of the instruction(optional)
489460 :return: An Instruction object
490461
491462 Example use::
@@ -506,17 +477,15 @@ def assemble_one(assembler, pc=0):
506477 operand = None
507478
508479 return EVMAsm .Instruction (opcode , name , operand_size , pops , pushes , gas , description , operand = operand , pc = pc )
509- except Exception as e :
510- print "Exception" , repr (e )
511-
480+ except BaseException :
512481 raise Exception ("Something wrong at pc %d" % pc )
513482
514483 @staticmethod
515484 def assemble_all (assembler , pc = 0 ):
516485 ''' Assemble a sequence of textual representation of EVM instructions
517486
518487 :param assembler: assembler code for any number of instructions
519- :param pc: program counter of the first instruction (optional)
488+ :param pc: program counter of the first instruction(optional)
520489 :return: An generator of Instruction objects
521490
522491 Example use::
@@ -550,7 +519,7 @@ def disassemble_one(bytecode, pc=0):
550519
551520 :param bytecode: the bytecode stream
552521 :type bytecode: bytearray or str
553- :param pc: program counter of the instruction (optional)
522+ :param pc: program counter of the instruction(optional)
554523 :type bytecode: iterator/sequence/str
555524 :return: an Instruction object
556525
@@ -559,11 +528,11 @@ def disassemble_one(bytecode, pc=0):
559528 >>> print EVMAsm.disassemble_one('\x60 \x10 ')
560529
561530 '''
562- if isinstance (bytecode , str ):
563- bytecode = bytearray (bytecode )
531+ if isinstance (bytecode , ( str , bytes ) ):
532+ bytecode = bytearray (bytecode . encode () )
564533 bytecode = iter (bytecode )
565534 opcode = next (bytecode )
566- assert isinstance (opcode , ( int , long ) )
535+ assert isinstance (opcode , int )
567536
568537 invalid = ('INVALID' , 0 , 0 , 0 , 0 , 'Unknown opcode' )
569538 name , operand_size , pops , pushes , gas , description = EVMAsm ._table .get (opcode , invalid )
@@ -578,7 +547,7 @@ def disassemble_all(bytecode, pc=0):
578547 ''' Decode all instructions in bytecode
579548
580549 :param bytecode: an evm bytecode (binary)
581- :param pc: program counter of the first instruction (optional)
550+ :param pc: program counter of the first instruction(optional)
582551 :type bytecode: iterator/sequence/str
583552 :return: An generator of Instruction objects
584553
@@ -603,7 +572,7 @@ def disassemble_all(bytecode, pc=0):
603572 '''
604573
605574 if isinstance (bytecode , str ):
606- bytecode = bytearray (bytecode )
575+ bytecode = bytearray (bytecode . encode () )
607576 bytecode = iter (bytecode )
608577 while True :
609578 instr = EVMAsm .disassemble_one (bytecode , pc = pc )
@@ -615,7 +584,7 @@ def disassemble(bytecode, pc=0):
615584 ''' Disassemble an EVM bytecode
616585
617586 :param bytecode: binary representation of an evm bytecode (hexadecimal)
618- :param pc: program counter of the first instruction (optional)
587+ :param pc: program counter of the first instruction(optional)
619588 :type bytecode: str
620589 :return: the text representation of the aseembler code
621590
@@ -637,7 +606,7 @@ def assemble(asmcode, pc=0):
637606 ''' Assemble an EVM program
638607
639608 :param asmcode: an evm assembler program
640- :param pc: program counter of the first instruction (optional)
609+ :param pc: program counter of the first instruction(optional)
641610 :type asmcode: str
642611 :return: the hex representation of the bytecode
643612
@@ -653,14 +622,14 @@ def assemble(asmcode, pc=0):
653622 ...
654623 "\x60 \x60 \x60 \x40 \x52 \x60 \x02 \x61 \x01 \x00 "
655624 '''
656- return '' .join (map ( lambda x : x .bytes , EVMAsm .assemble_all (asmcode , pc = pc )) )
625+ return '' .join ([ x .bytes for x in EVMAsm .assemble_all (asmcode , pc = pc )] )
657626
658627 @staticmethod
659628 def disassemble_hex (bytecode , pc = 0 ):
660629 ''' Disassemble an EVM bytecode
661630
662631 :param bytecode: canonical representation of an evm bytecode (hexadecimal)
663- :param pc: program counter of the first instruction (optional)
632+ :param pc: program counter of the first instruction(optional)
664633 :type bytecode: str
665634 :return: the text representation of the aseembler code
666635
@@ -677,15 +646,15 @@ def disassemble_hex(bytecode, pc=0):
677646 '''
678647 if bytecode .startswith ('0x' ):
679648 bytecode = bytecode [2 :]
680- bytecode = bytecode .decode ( 'hex' )
649+ bytecode = unhexlify ( bytecode .encode () )
681650 return EVMAsm .disassemble (bytecode , pc = pc )
682651
683652 @staticmethod
684653 def assemble_hex (asmcode , pc = 0 ):
685654 ''' Assemble an EVM program
686655
687656 :param asmcode: an evm assembler program
688- :param pc: program counter of the first instruction (optional)
657+ :param pc: program counter of the first instruction(optional)
689658 :type asmcode: str
690659 :return: the hex representation of the bytecode
691660
@@ -701,4 +670,4 @@ def assemble_hex(asmcode, pc=0):
701670 ...
702671 "0x6060604052600261010"
703672 '''
704- return '0x' + EVMAsm .assemble (asmcode , pc = pc ).encode ('hex' )
673+ return '0x' + hexlify ( EVMAsm .assemble (asmcode , pc = pc ).encode ()). decode ( )
0 commit comments