Add support for dynamic function as state variable

Add support for array/mapping of dynamic function
Allow PUSH operator (slithIR) to push Function
pull/55/head
Josselin 6 years ago
parent 836f3bab33
commit 0c7a4542ca
  1. 2
      slither/slithir/operations/internal_dynamic_call.py
  2. 3
      slither/slithir/operations/push.py
  3. 28
      slither/solc_parsing/expressions/expression_parsing.py

@ -37,7 +37,7 @@ class InternalDynamicCall(Call, OperationWithLValue):
lvalue = '{}({}) = '.format(self.lvalue, ','.join(str(x) for x in self.lvalue.type))
else:
lvalue = '{}({}) = '.format(self.lvalue, self.lvalue.type)
txt = '{}INTERNAL_DYNAMIC_CALL, {}({})'
txt = '{}INTERNAL_DYNAMIC_CALL {}({})'
return txt.format(lvalue,
self.function.name,
','.join(args))

@ -1,12 +1,13 @@
import logging
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.core.declarations import Function
from slither.core.variables.variable import Variable
from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
class Push(OperationWithLValue):
def __init__(self, array, value):
assert is_valid_rvalue(value)
assert is_valid_rvalue(value) or isinstance(value, Function)
assert is_valid_lvalue(array)
self._value = value
self._lvalue = array

@ -26,14 +26,27 @@ from slither.core.declarations.function import Function
from slither.core.declarations.solidity_variables import SOLIDITY_VARIABLES, SOLIDITY_FUNCTIONS, SOLIDITY_VARIABLES_COMPOSED
from slither.core.declarations.solidity_variables import SolidityVariable, SolidityFunction, SolidityVariableComposed, solidity_function_signature
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.solidity_types.function_type import FunctionType
from slither.core.solidity_types import ElementaryType, ArrayType, MappingType, FunctionType
logger = logging.getLogger("ExpressionParsing")
class VariableNotFound(Exception): pass
def get_pointer_name(variable):
curr_type = variable.type
while(isinstance(curr_type, (ArrayType, MappingType))):
if isinstance(curr_type, ArrayType):
curr_type = curr_type.type
else:
assert isinstance(curr_type, MappingType)
curr_type = curr_type.type_to
if isinstance(curr_type, (FunctionType)):
return variable.name + curr_type.parameters_signature
return None
def find_variable(var_name, caller_context):
if isinstance(caller_context, Contract):
@ -55,15 +68,20 @@ def find_variable(var_name, caller_context):
# function test(function(uint) internal returns(bool) t) interna{
# Will have a local variable t which will match the signature
# t(uint256)
func_variables_ptr = {f.name + f.type.parameters_signature : f for f in function.variables
if isinstance(f.type, FunctionType)}
if var_name in func_variables_ptr:
func_variables_ptr = {get_pointer_name(f) : f for f in function.variables}
if var_name and var_name in func_variables_ptr:
return func_variables_ptr[var_name]
contract_variables = contract.variables_as_dict()
if var_name in contract_variables:
return contract_variables[var_name]
# A state variable can be a pointer
conc_variables_ptr = {get_pointer_name(f) : f for f in contract.variables}
if var_name and var_name in conc_variables_ptr:
return conc_variables_ptr[var_name]
functions = contract.functions_as_dict()
if var_name in functions:
return functions[var_name]

Loading…
Cancel
Save