From 8eec95be2a1579ecfc795374c623575818b86e77 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Wed, 25 Jan 2023 08:55:46 +0100 Subject: [PATCH] Types improvements --- .../core/declarations/function_top_level.py | 5 +- slither/core/solidity_types/array_type.py | 4 +- slither/slithir/convert.py | 76 +++++++--------- slither/slithir/utils/ssa.py | 89 +++++++------------ .../visitors/slithir/expression_to_slithir.py | 22 ++--- 5 files changed, 74 insertions(+), 122 deletions(-) diff --git a/slither/core/declarations/function_top_level.py b/slither/core/declarations/function_top_level.py index 93d7a983d..dbc193fdc 100644 --- a/slither/core/declarations/function_top_level.py +++ b/slither/core/declarations/function_top_level.py @@ -9,6 +9,7 @@ from slither.core.declarations.top_level import TopLevel if TYPE_CHECKING: from slither.core.compilation_unit import SlitherCompilationUnit from slither.core.scope.scope import FileScope + from slither.slithir.variables.state_variable import StateIRVariable class FunctionTopLevel(Function, TopLevel): @@ -78,7 +79,9 @@ class FunctionTopLevel(Function, TopLevel): ################################################################################### ################################################################################### - def generate_slithir_ssa(self, all_ssa_state_variables_instances: Dict[Any, Any]) -> None: + def generate_slithir_ssa( + self, all_ssa_state_variables_instances: Dict[str, "StateIRVariable"] + ) -> None: # pylint: disable=import-outside-toplevel from slither.slithir.utils.ssa import add_ssa_ir, transform_slithir_vars_to_ssa from slither.core.dominators.utils import ( diff --git a/slither/core/solidity_types/array_type.py b/slither/core/solidity_types/array_type.py index da626ef17..c873c639a 100644 --- a/slither/core/solidity_types/array_type.py +++ b/slither/core/solidity_types/array_type.py @@ -17,7 +17,7 @@ class ArrayType(Type): def __init__( self, t: Union["TypeAliasTopLevel", "ArrayType", "FunctionType", "ElementaryType"], - length: Optional[Union["Identifier", "Literal", "BinaryOperation"]], + length: Optional[Union["Identifier", Literal, "BinaryOperation"]], ) -> None: assert isinstance(t, Type) if length: @@ -49,7 +49,7 @@ class ArrayType(Type): return self._length @property - def length_value(self) -> Optional["Literal"]: + def length_value(self) -> Optional[Literal]: return self._length_value @property diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index b934efb9d..60ff545fa 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -165,7 +165,7 @@ def convert_expression(expression: Expression, node: "Node") -> List[Any]: ################################################################################### -def is_value(ins: slither.slithir.operations.operation.Operation) -> bool: +def is_value(ins: Operation) -> bool: if isinstance(ins, TmpCall): if isinstance(ins.ori, Member): if ins.ori.variable_right == "value": @@ -173,7 +173,7 @@ def is_value(ins: slither.slithir.operations.operation.Operation) -> bool: return False -def is_gas(ins: slither.slithir.operations.operation.Operation) -> bool: +def is_gas(ins: Operation) -> bool: if isinstance(ins, TmpCall): if isinstance(ins.ori, Member): if ins.ori.variable_right == "gas": @@ -293,7 +293,7 @@ def _find_function_from_parameter( return None -def is_temporary(ins: slither.slithir.operations.operation.Operation) -> bool: +def is_temporary(ins: Operation) -> bool: return isinstance( ins, (Argument, TmpNewElementaryType, TmpNewContract, TmpNewArray, TmpNewStructure), @@ -1153,12 +1153,8 @@ def can_be_low_level(ir: slither.slithir.operations.high_level_call.HighLevelCal def convert_to_low_level( - ir: slither.slithir.operations.high_level_call.HighLevelCall, -) -> Union[ - slither.slithir.operations.send.Send, - slither.slithir.operations.low_level_call.LowLevelCall, - slither.slithir.operations.transfer.Transfer, -]: + ir: HighLevelCall, +) -> Union[Send, LowLevelCall, Transfer,]: """ Convert to a transfer/send/or low level call The funciton assume to receive a correct IR @@ -1198,7 +1194,7 @@ def convert_to_low_level( raise SlithIRError(f"Incorrect conversion to low level {ir}") -def can_be_solidity_func(ir: slither.slithir.operations.high_level_call.HighLevelCall) -> bool: +def can_be_solidity_func(ir: HighLevelCall) -> bool: if not isinstance(ir, HighLevelCall): return False return ir.destination.name == "abi" and ir.function_name in [ @@ -1212,8 +1208,8 @@ def can_be_solidity_func(ir: slither.slithir.operations.high_level_call.HighLeve def convert_to_solidity_func( - ir: slither.slithir.operations.high_level_call.HighLevelCall, -) -> slither.slithir.operations.solidity_call.SolidityCall: + ir: HighLevelCall, +) -> SolidityCall: """ Must be called after can_be_solidity_func :param ir: @@ -1250,8 +1246,8 @@ def convert_to_solidity_func( def convert_to_push_expand_arr( - ir: slither.slithir.operations.high_level_call.HighLevelCall, node: "Node", ret: List[Any] -) -> slither.slithir.variables.temporary.TemporaryVariable: + ir: HighLevelCall, node: "Node", ret: List[Any] +) -> TemporaryVariable: arr = ir.destination length = ReferenceVariable(node) @@ -1287,14 +1283,14 @@ def convert_to_push_expand_arr( def convert_to_push_set_val( - ir: slither.slithir.operations.high_level_call.HighLevelCall, + ir: HighLevelCall, node: "Node", - length_val: slither.slithir.variables.temporary.TemporaryVariable, + length_val: TemporaryVariable, ret: List[ Union[ - slither.slithir.operations.length.Length, - slither.slithir.operations.assignment.Assignment, - slither.slithir.operations.binary.Binary, + Length, + Assignment, + Binary, ] ], ) -> None: @@ -1417,21 +1413,16 @@ def convert_to_pop(ir, node): def look_for_library_or_top_level( - contract: slither.core.declarations.contract.Contract, - ir: slither.slithir.operations.high_level_call.HighLevelCall, + contract: Contract, + ir: HighLevelCall, using_for, t: Union[ - slither.core.solidity_types.user_defined_type.UserDefinedType, - slither.core.solidity_types.elementary_type.ElementaryType, + UserDefinedType, + ElementaryType, str, TypeAliasTopLevel, ], -) -> Optional[ - Union[ - slither.slithir.operations.library_call.LibraryCall, - slither.slithir.operations.internal_call.InternalCall, - ] -]: +) -> Optional[Union[LibraryCall, InternalCall,]]: for destination in using_for[t]: if isinstance(destination, FunctionTopLevel) and destination.name == ir.function_name: arguments = [ir.destination] + ir.arguments @@ -1477,13 +1468,8 @@ def look_for_library_or_top_level( def convert_to_library_or_top_level( - ir: slither.slithir.operations.high_level_call.HighLevelCall, node: "Node", using_for -) -> Optional[ - Union[ - slither.slithir.operations.library_call.LibraryCall, - slither.slithir.operations.internal_call.InternalCall, - ] -]: + ir: HighLevelCall, node: "Node", using_for +) -> Optional[Union[LibraryCall, InternalCall,]]: # We use contract_declarer, because Solidity resolve the library # before resolving the inheritance. # Though we could use .contract as libraries cannot be shadowed @@ -1504,8 +1490,8 @@ def convert_to_library_or_top_level( def get_type( t: Union[ - slither.core.solidity_types.user_defined_type.UserDefinedType, - slither.core.solidity_types.elementary_type.ElementaryType, + UserDefinedType, + ElementaryType, ] ) -> str: """ @@ -1526,9 +1512,7 @@ def _can_be_implicitly_converted(source: str, target: str) -> bool: return source == target -def convert_type_library_call( - ir: HighLevelCall, lib_contract: Contract -) -> Optional[slither.slithir.operations.library_call.LibraryCall]: +def convert_type_library_call(ir: HighLevelCall, lib_contract: Contract) -> Optional[LibraryCall]: func = None candidates = [ f @@ -1739,7 +1723,7 @@ def convert_type_of_high_and_internal_level_call( ################################################################################### -def find_references_origin(irs: List[Any]) -> None: +def find_references_origin(irs: List[Operation]) -> None: """ Make lvalue of each Index, Member operation points to the left variable @@ -1776,7 +1760,7 @@ def remove_temporary(result): return result -def remove_unused(result: List[Any]) -> List[Any]: +def remove_unused(result: List[Operation]) -> List[Operation]: removed = True if not result: @@ -1823,7 +1807,7 @@ def remove_unused(result: List[Any]) -> List[Any]: ################################################################################### -def convert_constant_types(irs: List[Any]) -> None: +def convert_constant_types(irs: List[Operation]) -> None: """ late conversion of uint -> type for constant (Literal) :param irs: @@ -1899,7 +1883,7 @@ def convert_constant_types(irs: List[Any]) -> None: ################################################################################### -def convert_delete(irs: List[Any]) -> None: +def convert_delete(irs: List[Operation]) -> None: """ Convert the lvalue of the Delete to point to the variable removed This can only be done after find_references_origin is called @@ -1935,7 +1919,7 @@ def _find_source_mapping_references(irs: List[Operation]) -> None: ################################################################################### -def apply_ir_heuristics(irs: List[Operation], node: "Node") -> List[Any]: +def apply_ir_heuristics(irs: List[Operation], node: "Node") -> List[Operation]: """ Apply a set of heuristic to improve slithIR """ diff --git a/slither/slithir/utils/ssa.py b/slither/slithir/utils/ssa.py index ebc50e788..156914b61 100644 --- a/slither/slithir/utils/ssa.py +++ b/slither/slithir/utils/ssa.py @@ -215,18 +215,12 @@ def add_ssa_ir( def generate_ssa_irs( node: Node, - local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable], - all_local_variables_instances: Dict[ - str, slither.slithir.variables.local_variable.LocalIRVariable - ], - state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable], - all_state_variables_instances: Dict[ - str, slither.slithir.variables.state_variable.StateIRVariable - ], - init_local_variables_instances: Dict[ - str, slither.slithir.variables.local_variable.LocalIRVariable - ], - visited: List[Union[Node, Any]], + local_variables_instances: Dict[str, LocalIRVariable], + all_local_variables_instances: Dict[str, LocalIRVariable], + state_variables_instances: Dict[str, StateIRVariable], + all_state_variables_instances: Dict[str, StateIRVariable], + init_local_variables_instances: Dict[str, LocalIRVariable], + visited: List[Node], ) -> None: if node in visited: @@ -347,14 +341,11 @@ def generate_ssa_irs( def last_name( n: Node, var: Union[ - slither.slithir.variables.state_variable.StateIRVariable, - slither.slithir.variables.local_variable.LocalIRVariable, + StateIRVariable, + LocalIRVariable, ], - init_vars: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable], -) -> Union[ - slither.slithir.variables.state_variable.StateIRVariable, - slither.slithir.variables.local_variable.LocalIRVariable, -]: + init_vars: Dict[str, LocalIRVariable], +) -> Union[StateIRVariable, LocalIRVariable,]: candidates = [] # Todo optimize by creating a variables_ssa_written attribute for ir_ssa in n.irs_ssa: @@ -375,7 +366,7 @@ def last_name( def is_used_later( initial_node: Node, - variable: Union[slither.slithir.variables.state_variable.StateIRVariable, LocalVariable], + variable: Union[StateIRVariable, LocalVariable], ) -> bool: # TODO: does not handle the case where its read and written in the declaration node # It can be problematic if this happens in a loop/if structure @@ -425,14 +416,10 @@ def is_used_later( def update_lvalue( new_ir: Operation, node: Node, - local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable], - all_local_variables_instances: Dict[ - str, slither.slithir.variables.local_variable.LocalIRVariable - ], - state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable], - all_state_variables_instances: Dict[ - str, slither.slithir.variables.state_variable.StateIRVariable - ], + local_variables_instances: Dict[str, LocalIRVariable], + all_local_variables_instances: Dict[str, LocalIRVariable], + state_variables_instances: Dict[str, StateIRVariable], + all_state_variables_instances: Dict[str, StateIRVariable], ) -> None: if isinstance(new_ir, OperationWithLValue): lvalue = new_ir.lvalue @@ -476,10 +463,8 @@ def update_lvalue( def initiate_all_local_variables_instances( nodes: List[Node], - local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable], - all_local_variables_instances: Dict[ - str, slither.slithir.variables.local_variable.LocalIRVariable - ], + local_variables_instances: Dict[str, LocalIRVariable], + all_local_variables_instances: Dict[str, LocalIRVariable], ) -> None: for node in nodes: if node.variable_declaration: @@ -500,17 +485,11 @@ def initiate_all_local_variables_instances( def fix_phi_rvalues_and_storage_ref( node: Node, - local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable], - all_local_variables_instances: Dict[ - str, slither.slithir.variables.local_variable.LocalIRVariable - ], - state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable], - all_state_variables_instances: Dict[ - str, slither.slithir.variables.state_variable.StateIRVariable - ], - init_local_variables_instances: Dict[ - str, slither.slithir.variables.local_variable.LocalIRVariable - ], + local_variables_instances: Dict[str, LocalIRVariable], + all_local_variables_instances: Dict[str, LocalIRVariable], + state_variables_instances: Dict[str, StateIRVariable], + all_state_variables_instances: Dict[str, StateIRVariable], + init_local_variables_instances: Dict[str, LocalIRVariable], ) -> None: for ir in node.irs_ssa: if isinstance(ir, (Phi)) and not ir.rvalues: @@ -609,18 +588,12 @@ def add_phi_origins( def get( variable, - local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable], - state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable], - temporary_variables_instances: Dict[ - int, slither.slithir.variables.temporary_ssa.TemporaryVariableSSA - ], - reference_variables_instances: Dict[ - int, slither.slithir.variables.reference_ssa.ReferenceVariableSSA - ], - tuple_variables_instances: Dict[int, slither.slithir.variables.tuple_ssa.TupleVariableSSA], - all_local_variables_instances: Dict[ - str, slither.slithir.variables.local_variable.LocalIRVariable - ], + local_variables_instances: Dict[str, LocalIRVariable], + state_variables_instances: Dict[str, StateIRVariable], + temporary_variables_instances: Dict[int, TemporaryVariableSSA], + reference_variables_instances: Dict[int, ReferenceVariableSSA], + tuple_variables_instances: Dict[int, TupleVariableSSA], + all_local_variables_instances: Dict[str, LocalIRVariable], ): # variable can be None # for example, on LowLevelCall, ir.lvalue can be none @@ -706,9 +679,9 @@ def get_arguments(ir: Call, *instances) -> List[Any]: def get_rec_values( ir: Union[ - slither.slithir.operations.init_array.InitArray, - slither.slithir.operations.return_operation.Return, - slither.slithir.operations.new_array.NewArray, + InitArray, + Return, + NewArray, ], f: Callable, *instances, diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 3dd36e39b..132f9858a 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -119,15 +119,11 @@ _signed_to_unsigned = { def convert_assignment( - left: Union[ - LocalVariable, StateVariable, slither.slithir.variables.reference.ReferenceVariable - ], + left: Union[LocalVariable, StateVariable, ReferenceVariable], right: SourceMapping, - t: slither.core.expressions.assignment_operation.AssignmentOperationType, + t: AssignmentOperationType, return_type, -) -> Union[ - slither.slithir.operations.binary.Binary, slither.slithir.operations.assignment.Assignment -]: +) -> Union[Binary, Assignment]: if t == AssignmentOperationType.ASSIGN: return Assignment(left, right, return_type) if t == AssignmentOperationType.ASSIGN_OR: @@ -173,9 +169,7 @@ class ExpressionToSlithIR(ExpressionVisitor): def result(self) -> List[Any]: return self._result - def _post_assignement_operation( - self, expression: slither.core.expressions.assignment_operation.AssignmentOperation - ) -> None: + def _post_assignement_operation(self, expression: AssignmentOperation) -> None: left = get(expression.expression_left) right = get(expression.expression_right) if isinstance(left, list): # tuple expression: @@ -275,9 +269,7 @@ class ExpressionToSlithIR(ExpressionVisitor): set_val(expression, val) # pylint: disable=too-many-branches,too-many-statements,too-many-locals - def _post_call_expression( - self, expression: slither.core.expressions.call_expression.CallExpression - ) -> None: + def _post_call_expression(self, expression: CallExpression) -> None: assert isinstance(expression, CallExpression) @@ -387,11 +379,11 @@ class ExpressionToSlithIR(ExpressionVisitor): def _post_elementary_type_name_expression( self, - expression: slither.core.expressions.elementary_type_name_expression.ElementaryTypeNameExpression, + expression: ElementaryTypeNameExpression, ) -> None: set_val(expression, expression.type) - def _post_identifier(self, expression: slither.core.expressions.identifier.Identifier) -> None: + def _post_identifier(self, expression: Identifier) -> None: set_val(expression, expression.value) def _post_index_access(self, expression: IndexAccess) -> None: