Fix incorrect abi.decode translation

pull/332/head
Josselin 5 years ago
parent 9922eb499a
commit 1ef8dbe69d
  1. 65
      slither/slithir/convert.py
  2. 3
      slither/solc_parsing/declarations/function.py

@ -375,6 +375,10 @@ def propagate_types(ir, node):
if t is None: if t is None:
return return
if isinstance(t, ElementaryType) and t.name == 'address':
if can_be_solidity_func(ir):
return convert_to_solidity_func(ir)
# convert library # convert library
if t in using_for or '*' in using_for: if t in using_for or '*' in using_for:
new_ir = convert_to_library(ir, node, using_for) new_ir = convert_to_library(ir, node, using_for)
@ -392,7 +396,8 @@ def propagate_types(ir, node):
if isinstance(t, ElementaryType) and t.name == 'address': if isinstance(t, ElementaryType) and t.name == 'address':
if ir.destination.name == 'this': if ir.destination.name == 'this':
return convert_type_of_high_and_internal_level_call(ir, node.function.contract) return convert_type_of_high_and_internal_level_call(ir, node.function.contract)
return convert_to_low_level(ir) if can_be_low_level(ir):
return convert_to_low_level(ir)
# Convert push operations # Convert push operations
# May need to insert a new operation # May need to insert a new operation
@ -605,13 +610,21 @@ def extract_tmp_call(ins, contract):
################################################################################### ###################################################################################
################################################################################### ###################################################################################
def can_be_low_level(ir):
return ir.function_name in ['transfer',
'send',
'call',
'delegatecall',
'callcode',
'staticcall']
def convert_to_low_level(ir): def convert_to_low_level(ir):
""" """
Convert to a transfer/send/or low level call Convert to a transfer/send/or low level call
The funciton assume to receive a correct IR The funciton assume to receive a correct IR
The checks must be done by the caller The checks must be done by the caller
Additionally convert abi... to solidityfunction Must be called after can_be_low_level
""" """
if ir.function_name == 'transfer': if ir.function_name == 'transfer':
assert len(ir.arguments) == 1 assert len(ir.arguments) == 1
@ -622,20 +635,6 @@ def convert_to_low_level(ir):
ir = Send(ir.destination, ir.arguments[0], ir.lvalue) ir = Send(ir.destination, ir.arguments[0], ir.lvalue)
ir.lvalue.set_type(ElementaryType('bool')) ir.lvalue.set_type(ElementaryType('bool'))
return ir return ir
elif ir.destination.name == 'abi' and ir.function_name in ['encode',
'encodePacked',
'encodeWithSelector',
'encodeWithSignature',
'decode']:
call = SolidityFunction('abi.{}()'.format(ir.function_name))
new_ir = SolidityCall(call, ir.nbr_arguments, ir.lvalue, ir.type_call)
new_ir.arguments = ir.arguments
if isinstance(call.return_type, list) and len(call.return_type) == 1:
new_ir.lvalue.set_type(call.return_type[0])
else:
new_ir.lvalue.set_type(call.return_type)
return new_ir
elif ir.function_name in ['call', elif ir.function_name in ['call',
'delegatecall', 'delegatecall',
'callcode', 'callcode',
@ -652,6 +651,29 @@ def convert_to_low_level(ir):
return new_ir return new_ir
raise SlithIRError('Incorrect conversion to low level {}'.format(ir)) raise SlithIRError('Incorrect conversion to low level {}'.format(ir))
def can_be_solidity_func(ir):
return ir.destination.name == 'abi' and ir.function_name in ['encode',
'encodePacked',
'encodeWithSelector',
'encodeWithSignature',
'decode']
def convert_to_solidity_func(ir):
"""
Must be called after can_be_solidity_func
:param ir:
:return:
"""
call = SolidityFunction('abi.{}()'.format(ir.function_name))
new_ir = SolidityCall(call, ir.nbr_arguments, ir.lvalue, ir.type_call)
new_ir.arguments = ir.arguments
if isinstance(call.return_type, list) and len(call.return_type) == 1:
new_ir.lvalue.set_type(call.return_type[0])
else:
new_ir.lvalue.set_type(call.return_type)
return new_ir
def convert_to_push(ir, node): def convert_to_push(ir, node):
""" """
Convert a call to a PUSH operaiton Convert a call to a PUSH operaiton
@ -815,12 +837,11 @@ def convert_type_of_high_and_internal_level_call(ir, contract):
func = function func = function
break break
# lowlelvel lookup needs to be done at last step # lowlelvel lookup needs to be done at last step
if not func and ir.function_name in ['call', if not func:
'delegatecall', if can_be_low_level(ir):
'callcode', return convert_to_low_level(ir)
'transfer', if can_be_solidity_func(ir):
'send']: return convert_to_solidity_func(ir)
return convert_to_low_level(ir)
if not func: if not func:
logger.error('Function not found {}'.format(sig)) logger.error('Function not found {}'.format(sig))
ir.function = func ir.function = func

@ -499,7 +499,8 @@ class FunctionSolc(Function):
variables = statement['declarations'] variables = statement['declarations']
count = len(variables) count = len(variables)
if statement['initialValue']['nodeType'] == 'TupleExpression': if statement['initialValue']['nodeType'] == 'TupleExpression' and \
len(statement['initialValue']['components']) == count:
inits = statement['initialValue']['components'] inits = statement['initialValue']['components']
i = 0 i = 0
new_node = node new_node = node

Loading…
Cancel
Save