Types improvements

pull/1640/head
Feist Josselin 2 years ago
parent faba84efc1
commit 8eec95be2a
  1. 5
      slither/core/declarations/function_top_level.py
  2. 4
      slither/core/solidity_types/array_type.py
  3. 76
      slither/slithir/convert.py
  4. 89
      slither/slithir/utils/ssa.py
  5. 22
      slither/visitors/slithir/expression_to_slithir.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 (

@ -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

@ -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
"""

@ -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,

@ -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:

Loading…
Cancel
Save