@ -12,15 +12,15 @@ from slither.solc_parsing.declarations.modifier import ModifierSolc
from slither . solc_parsing . declarations . structure import StructureSolc
from slither . solc_parsing . declarations . structure import StructureSolc
from slither . solc_parsing . solidity_types . type_parsing import parse_type
from slither . solc_parsing . solidity_types . type_parsing import parse_type
from slither . solc_parsing . variables . state_variable import StateVariableSolc
from slither . solc_parsing . variables . state_variable import StateVariableSolc
from slither . solc_parsing . exceptions import ParsingError
from slither . solc_parsing . exceptions import ParsingError , VariableNotFound
logger = logging . getLogger ( " ContractSolcParsing " )
logger = logging . getLogger ( " ContractSolcParsing " )
class ContractSolc04 ( Contract ) :
class ContractSolc04 ( Contract ) :
def __init__ ( self , slitherSolc , data ) :
def __init__ ( self , slitherSolc , data ) :
#assert slitherSolc.solc_version.startswith('0.4')
# assert slitherSolc.solc_version.startswith('0.4')
super ( ContractSolc04 , self ) . __init__ ( )
super ( ContractSolc04 , self ) . __init__ ( )
self . set_slither ( slitherSolc )
self . set_slither ( slitherSolc )
@ -54,7 +54,6 @@ class ContractSolc04(Contract):
self . _parse_contract_info ( )
self . _parse_contract_info ( )
self . _parse_contract_items ( )
self . _parse_contract_items ( )
###################################################################################
###################################################################################
###################################################################################
###################################################################################
# region General Properties
# region General Properties
@ -190,7 +189,7 @@ class ContractSolc04(Contract):
elif item [ self . get_key ( ) ] == ' UsingForDirective ' :
elif item [ self . get_key ( ) ] == ' UsingForDirective ' :
self . _usingForNotParsed . append ( item )
self . _usingForNotParsed . append ( item )
else :
else :
raise ParsingError ( ' Unknown contract item: ' + item [ self . get_key ( ) ] )
raise ParsingError ( ' Unknown contract item: ' + item [ self . get_key ( ) ] )
return
return
def _parse_struct ( self , struct ) :
def _parse_struct ( self , struct ) :
@ -263,7 +262,6 @@ class ContractSolc04(Contract):
for function in self . _functionsNotParsed :
for function in self . _functionsNotParsed :
self . _parse_function ( function )
self . _parse_function ( function )
self . _functionsNotParsed = None
self . _functionsNotParsed = None
return
return
@ -275,41 +273,51 @@ class ContractSolc04(Contract):
###################################################################################
###################################################################################
###################################################################################
###################################################################################
def log_incorrect_parsing ( self ) :
self . _is_incorrectly_parsed = True
def analyze_content_modifiers ( self ) :
def analyze_content_modifiers ( self ) :
try :
for modifier in self . modifiers :
for modifier in self . modifiers :
modifier . analyze_content ( )
modifier . analyze_content ( )
except ( VariableNotFound , KeyError ) :
self . log_incorrect_parsing ( )
return
return
def analyze_content_functions ( self ) :
def analyze_content_functions ( self ) :
try :
for function in self . functions :
for function in self . functions :
function . analyze_content ( )
function . analyze_content ( )
except ( VariableNotFound , KeyError ) :
self . log_incorrect_parsing ( )
return
return
def analyze_params_modifiers ( self ) :
def analyze_params_modifiers ( self ) :
try :
elements_no_params = self . _modifiers_no_params
elements_no_params = self . _modifiers_no_params
getter = lambda f : f . modifiers
getter = lambda f : f . modifiers
getter_available = lambda f : f . modifiers_declared
getter_available = lambda f : f . modifiers_declared
Cls = ModifierSolc
Cls = ModifierSolc
self . _modifiers = self . _analyze_params_elements ( elements_no_params , getter , getter_available , Cls )
self . _modifiers = self . _analyze_params_elements ( elements_no_params , getter , getter_available , Cls )
except ( VariableNotFound , KeyError ) :
self . log_incorrect_parsing ( )
self . _modifiers_no_params = [ ]
self . _modifiers_no_params = [ ]
return
return
def analyze_params_functions ( self ) :
def analyze_params_functions ( self ) :
try :
elements_no_params = self . _functions_no_params
elements_no_params = self . _functions_no_params
getter = lambda f : f . functions
getter = lambda f : f . functions
getter_available = lambda f : f . functions_declared
getter_available = lambda f : f . functions_declared
Cls = FunctionSolc
Cls = FunctionSolc
self . _functions = self . _analyze_params_elements ( elements_no_params , getter , getter_available , Cls )
self . _functions = self . _analyze_params_elements ( elements_no_params , getter , getter_available , Cls )
except ( VariableNotFound , KeyError ) :
self . log_incorrect_parsing ( )
self . _functions_no_params = [ ]
self . _functions_no_params = [ ]
return
return
def _analyze_params_elements ( self , elements_no_params , getter , getter_available , Cls ) :
def _analyze_params_elements ( self , elements_no_params , getter , getter_available , Cls ) :
"""
"""
Analyze the parameters of the given elements ( Function or Modifier ) .
Analyze the parameters of the given elements ( Function or Modifier ) .
@ -323,6 +331,7 @@ class ContractSolc04(Contract):
"""
"""
all_elements = { }
all_elements = { }
try :
for father in self . inheritance :
for father in self . inheritance :
for element in getter ( father ) :
for element in getter ( father ) :
elem = Cls ( element . _functionNotParsed , self , element . contract_declarer )
elem = Cls ( element . _functionNotParsed , self , element . contract_declarer )
@ -355,23 +364,20 @@ class ContractSolc04(Contract):
if accessible_elements [ element . full_name ] != all_elements [ element . canonical_name ] :
if accessible_elements [ element . full_name ] != all_elements [ element . canonical_name ] :
element . is_shadowed = True
element . is_shadowed = True
accessible_elements [ element . full_name ] . shadows = True
accessible_elements [ element . full_name ] . shadows = True
except ( VariableNotFound , KeyError ) :
self . log_incorrect_parsing ( )
return all_elements
return all_elements
def analyze_constant_state_variables ( self ) :
def analyze_constant_state_variables ( self ) :
from slither . solc_parsing . expressions . expression_parsing import VariableNotFound
for var in self . variables :
for var in self . variables :
if var . is_constant :
if var . is_constant :
# cant parse constant expression based on function calls
# cant parse constant expression based on function calls
try :
try :
var . analyze ( self )
var . analyze ( self )
except VariableNotFound :
except ( VariableNotFound , KeyError ) :
pass
pass
return
return
def _create_node ( self , func , counter , variable ) :
def _create_node ( self , func , counter , variable ) :
# Function uses to create node for state variable declaration statements
# Function uses to create node for state variable declaration statements
node = Node ( NodeType . OTHER_ENTRYPOINT , counter )
node = Node ( NodeType . OTHER_ENTRYPOINT , counter )
@ -405,7 +411,7 @@ class ContractSolc04(Contract):
prev_node = self . _create_node ( constructor_variable , 0 , variable_candidate )
prev_node = self . _create_node ( constructor_variable , 0 , variable_candidate )
variable_candidate . node_initialization = prev_node
variable_candidate . node_initialization = prev_node
counter = 1
counter = 1
for v in self . state_variables [ idx + 1 : ] :
for v in self . state_variables [ idx + 1 : ] :
if v . expression and not v . is_constant :
if v . expression and not v . is_constant :
next_node = self . _create_node ( constructor_variable , counter , v )
next_node = self . _create_node ( constructor_variable , counter , v )
v . node_initialization = next_node
v . node_initialization = next_node
@ -430,7 +436,7 @@ class ContractSolc04(Contract):
prev_node = self . _create_node ( constructor_variable , 0 , variable_candidate )
prev_node = self . _create_node ( constructor_variable , 0 , variable_candidate )
variable_candidate . node_initialization = prev_node
variable_candidate . node_initialization = prev_node
counter = 1
counter = 1
for v in self . state_variables [ idx + 1 : ] :
for v in self . state_variables [ idx + 1 : ] :
if v . expression and v . is_constant :
if v . expression and v . is_constant :
next_node = self . _create_node ( constructor_variable , counter , v )
next_node = self . _create_node ( constructor_variable , counter , v )
v . node_initialization = next_node
v . node_initialization = next_node
@ -440,16 +446,16 @@ class ContractSolc04(Contract):
break
break
def analyze_state_variables ( self ) :
def analyze_state_variables ( self ) :
try :
for var in self . variables :
for var in self . variables :
var . analyze ( self )
var . analyze ( self )
return
return
except ( VariableNotFound , KeyError ) :
self . log_incorrect_parsing ( )
def analyze_using_for ( self ) :
def analyze_using_for ( self ) :
try :
for father in self . inheritance :
for father in self . inheritance :
self . _using_for . update ( father . using_for )
self . _using_for . update ( father . using_for )
@ -477,9 +483,11 @@ class ContractSolc04(Contract):
self . using_for [ old ] = [ ]
self . using_for [ old ] = [ ]
self . _using_for [ old ] . append ( new )
self . _using_for [ old ] . append ( new )
self . _usingForNotParsed = [ ]
self . _usingForNotParsed = [ ]
except ( VariableNotFound , KeyError ) :
self . log_incorrect_parsing ( )
def analyze_enums ( self ) :
def analyze_enums ( self ) :
try :
for father in self . inheritance :
for father in self . inheritance :
self . _enums . update ( father . enums_as_dict ( ) )
self . _enums . update ( father . enums_as_dict ( ) )
@ -488,6 +496,8 @@ class ContractSolc04(Contract):
# at the same time
# at the same time
self . _analyze_enum ( enum )
self . _analyze_enum ( enum )
self . _enumsNotParsed = None
self . _enumsNotParsed = None
except ( VariableNotFound , KeyError ) :
self . log_incorrect_parsing ( )
def _analyze_enum ( self , enum ) :
def _analyze_enum ( self , enum ) :
# Enum can be parsed in one pass
# Enum can be parsed in one pass
@ -517,10 +527,14 @@ class ContractSolc04(Contract):
struct . analyze ( )
struct . analyze ( )
def analyze_structs ( self ) :
def analyze_structs ( self ) :
try :
for struct in self . structures :
for struct in self . structures :
self . _analyze_struct ( struct )
self . _analyze_struct ( struct )
except ( VariableNotFound , KeyError ) :
self . log_incorrect_parsing ( )
def analyze_events ( self ) :
def analyze_events ( self ) :
try :
for father in self . inheritance_reverse :
for father in self . inheritance_reverse :
self . _events . update ( father . events_as_dict ( ) )
self . _events . update ( father . events_as_dict ( ) )
@ -530,11 +544,11 @@ class ContractSolc04(Contract):
event . set_contract ( self )
event . set_contract ( self )
event . set_offset ( event_to_parse [ ' src ' ] , self . slither )
event . set_offset ( event_to_parse [ ' src ' ] , self . slither )
self . _events [ event . full_name ] = event
self . _events [ event . full_name ] = event
except ( VariableNotFound , KeyError ) :
self . log_incorrect_parsing ( )
self . _eventsNotParsed = None
self . _eventsNotParsed = None
# endregion
# endregion
###################################################################################
###################################################################################
###################################################################################
###################################################################################
@ -578,6 +592,28 @@ class ContractSolc04(Contract):
for func in self . functions + self . modifiers :
for func in self . functions + self . modifiers :
func . fix_phi ( last_state_variables_instances , initial_state_variables_instances )
func . fix_phi ( last_state_variables_instances , initial_state_variables_instances )
# endregion
###################################################################################
###################################################################################
# region Internal
###################################################################################
###################################################################################
def delete_content ( self ) :
"""
Remove everything not parsed from the contract
This is used only if something went wrong with the inheritance parsing
: return :
"""
self . _functionsNotParsed = [ ]
self . _modifiersNotParsed = [ ]
self . _functions_no_params = [ ]
self . _modifiers_no_params = [ ]
self . _eventsNotParsed = [ ]
self . _variablesNotParsed = [ ]
self . _enumsNotParsed = [ ]
self . _structuresNotParsed = [ ]
self . _usingForNotParsed = [ ]
# endregion
# endregion
###################################################################################
###################################################################################