https://github.com/trailofbits/manticore
Raw File
Tip revision: bd7c417dcd44c58b2c30f737c19497022902ef31 authored by feliam on 29 June 2018, 16:54:08 UTC
Merge branch 'dev-evm-fixslice' into yolo_master
Tip revision: bd7c417
abitypes.py
# Minimal ethereum type signature parser.
# This parses the signature and types used to calculate the function hash
import ply.yacc as yacc
# Lexer
# ------------------------------------------------------------
import ply.lex as lex
import re
# List of token names.   This is always required
tokens = (
    'COMMA',
    'LPAREN',
    'RPAREN',
    'LBRAKET',
    'RBRAKET',
    'NUMBER',

    'UINTN',
    'INTN',
    'UINT',
    'INT',
    'BOOL',
    'FIXEDMN',
    'UFIXEDMN',
    'ADDRESS',
    'FIXED',
    'UFIXED',
    'FUNCTION',
    'BYTESM',
    'BYTES',
    'STRING',
)

# Regular expression rules for simple tokens
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_LBRAKET = r'\['
t_RBRAKET = r'\]'
t_COMMA = r'\,'


def t_NUMBER(t):
    r"\d+"
    t.value = int(t.value)
    return t


# A regular expression rule with some action code
def t_UINTN(t):
    r"uint(?P<size>256|248|240|232|224|216|208|200|192|184|176|168|160|152|144|136|128|120|112|104|96|88|80|72|64|56|48|40|32|24|16|8)"
    size = int(t.lexer.lexmatch.group('size'))
    t.value = ('uint', size)
    return t


def t_ADDRESS(t):
    r"address"
    t.value = ('uint', 160)
    return t


def t_BOOL(t):
    r"bool"
    t.value = ('uint', 8)
    return t


def t_UINT(t):
    r"uint"
    t.value = ('uint', 256)
    return t


def t_INTN(t):
    r"int(?P<size>256|248|240|232|224|216|208|200|192|184|176|168|160|152|144|136|128|120|112|104|96|88|80|72|64|56|48|40|32|24|16|8)"
    size = int(t.lexer.lexmatch.group('size'))
    t.value = ('int', size)
    return t


def t_INT(t):
    r"int"
    t.value = ('int', 256)
    return t


def t_FIXEDMN(t):
    r"^fixed(?P<M>256|248|240|232|224|216|208|200|192|184|176|168|160|152|144|136|128|120|112|104|96|88|80|72|64|56|48|40|32|24|16|8)x(?P<N>80|79|78|77|76|75|74|73|72|71|70|69|68|67|66|65|64|63|62|61|60|59|58|57|56|55|54|53|52|51|50|49|48|47|46|45|44|43|42|41|40|39|38|37|36|35|34|33|32|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1)"
    M = int(t.lexer.lexmatch.group('M'))
    N = int(t.lexer.lexmatch.group('N'))
    t.value = ("fixed", M, N)
    return t


def t_FIXED(t):
    r"fixed"
    t.value = ('fixed', 128, 18)
    return t


def t_UFIXEDMN(t):
    r"ufixed(?P<M>256|248|240|232|224|216|208|200|192|184|176|168|160|152|144|136|128|120|112|104|96|88|80|72|64|56|48|40|32|24|16|8)x(?P<N>80|79|78|77|76|75|74|73|72|71|70|69|68|67|66|65|64|63|62|61|60|59|58|57|56|55|54|53|52|51|50|49|48|47|46|45|44|43|42|41|40|39|38|37|36|35|34|33|32|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1)"
    M = int(t.lexer.lexmatch.group('M'))
    N = int(t.lexer.lexmatch.group('N'))
    t.value = ("ufixed", M, N)
    return t


def t_UFIXED(t):
    r"ufixed"
    t.value = ('ufixed', 128, 18)
    return t


def t_BYTESM(t):
    r"bytes(?P<nbytes>32|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1)"
    size = int(t.lexer.lexmatch.group('nbytes'))
    t.value = ('bytesM', size)
    return t


def t_BYTES(t):
    r"bytes"
    t.value = ('bytes',)
    return t


def t_STRING(t):
    r"string"
    t.value = ('string',)
    return t


def t_FUNCTION(t):
    r"function"
    t.value = ('function',)
    return t


# Error handling rule
def t_error(t):
    raise Exception("Illegal character '%s'" % t.value[0])


# Build the lexer
lexer = lex.lex()


# parser
def p_basic_type(p):
    '''
     T : UINTN
     T : UINT
     T : INTN
     T : INT
     T : ADDRESS
     T : BOOL
     T : FIXEDMN
     T : UFIXEDMN
     T : FIXED
     T : UFIXED
     T : BYTESM
     T : FUNCTION
     T : BYTES
     T : STRING

    '''
    p[0] = p[1]


def p_type_list_one(p):
    '''
     TL : T
    '''
    p[0] = (p[1],)


def p_type_list(p):
    '''
     TL : T COMMA TL
    '''
    p[0] = (p[1],) + p[3]


def p_tuple(p):
    '''
     T : LPAREN TL RPAREN
    '''
    p[0] = ('tuple', p[2])


def p_tuple_empty(p):
    '''
     T : LPAREN RPAREN
    '''
    p[0] = ('tuple', ())


def p_dynamic_type(p):
    '''
     T : T LBRAKET RBRAKET
    '''
    reps = None
    base_type = p[1]
    p[0] = ('array', reps, base_type)


def p_dynamic_fixed_type(p):
    '''
     T : T LBRAKET NUMBER RBRAKET
    '''
    reps = int(p[3])
    base_type = p[1]
    p[0] = ('array', reps, base_type)


def p_error(p):
    raise Exception("Syntax Error at abitypes")
    #print("Syntax error at offset {:d}".format(lexer.lexpos))


parser = yacc.yacc()
parse = parser.parse


if __name__ == '__main__':
    #(((((((address,string,bytes)[1],int256)[0],bytes8[1])[],((address,string,bytes)[1],int256))[])[])[4])
    while True:
        try:
            s = raw_input('abitype > ')   # use input() on Python 3
        except EOFError:
            break
        print "R:", parser.parse(s, debug=True, tracking=True)
back to top