Remove core.children

pull/1673/head
Feist Josselin 2 years ago
parent 20a79519f3
commit 10109fc553
  1. 11
      slither/core/cfg/node.py
  2. 17
      slither/core/children/child_event.py
  3. 18
      slither/core/children/child_expression.py
  4. 17
      slither/core/children/child_function.py
  5. 17
      slither/core/children/child_inheritance.py
  6. 31
      slither/core/children/child_node.py
  7. 17
      slither/core/children/child_structure.py
  8. 13
      slither/core/declarations/contract_level.py
  9. 4
      slither/core/declarations/custom_error_contract.py
  10. 4
      slither/core/declarations/enum_contract.py
  11. 4
      slither/core/declarations/event.py
  12. 29
      slither/core/declarations/function_contract.py
  13. 4
      slither/core/declarations/structure_contract.py
  14. 6
      slither/core/declarations/top_level.py
  15. 10
      slither/core/slither_core.py
  16. 4
      slither/core/solidity_types/type_alias.py
  17. 5
      slither/core/variables/event_variable.py
  18. 17
      slither/core/variables/local_variable.py
  19. 4
      slither/core/variables/state_variable.py
  20. 19
      slither/core/variables/structure_variable.py
  21. 4
      slither/detectors/erc/incorrect_erc721_interface.py
  22. 4
      slither/detectors/operations/missing_events_arithmetic.py
  23. 4
      slither/detectors/statements/tx_origin.py
  24. 2
      slither/slithir/convert.py
  25. 4
      slither/slithir/operations/internal_dynamic_call.py
  26. 4
      slither/slithir/operations/new_structure.py
  27. 35
      slither/slithir/operations/operation.py
  28. 3
      slither/slithir/operations/solidity_call.py
  29. 4
      slither/slithir/operations/type_conversion.py
  30. 7
      slither/slithir/variables/reference.py
  31. 7
      slither/slithir/variables/temporary.py
  32. 7
      slither/slithir/variables/tuple.py
  33. 8
      slither/solc_parsing/declarations/contract.py
  34. 21
      slither/utils/output.py
  35. 2
      tests/test_ssa_generation.py

@ -5,7 +5,6 @@ from enum import Enum
from typing import Optional, List, Set, Dict, Tuple, Union, TYPE_CHECKING
from slither.all_exceptions import SlitherException
from slither.core.children.child_function import ChildFunction
from slither.core.declarations import Contract, Function
from slither.core.declarations.solidity_variables import (
SolidityVariable,
@ -106,7 +105,7 @@ class NodeType(Enum):
# I am not sure why, but pylint reports a lot of "no-member" issue that are not real (Josselin)
# pylint: disable=no-member
class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-methods
class Node(SourceMapping): # pylint: disable=too-many-public-methods
"""
Node class
@ -189,6 +188,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
self.scope: Union["Scope", "Function"] = scope
self.file_scope: "FileScope" = file_scope
self._function: Optional["Function"] = None
###################################################################################
###################################################################################
@ -224,6 +224,13 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
return True
return False
def set_function(self, function: "Function") -> None:
self._function = function
@property
def function(self) -> "Function":
return self._function
# endregion
###################################################################################
###################################################################################

@ -1,17 +0,0 @@
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from slither.core.declarations import Event
class ChildEvent:
def __init__(self) -> None:
super().__init__()
self._event = None
def set_event(self, event: "Event"):
self._event = event
@property
def event(self) -> "Event":
return self._event

@ -1,18 +0,0 @@
from typing import TYPE_CHECKING, Union
if TYPE_CHECKING:
from slither.core.expressions.expression import Expression
from slither.slithir.operations import Operation
class ChildExpression:
def __init__(self) -> None:
super().__init__()
self._expression = None
def set_expression(self, expression: Union["Expression", "Operation"]) -> None:
self._expression = expression
@property
def expression(self) -> Union["Expression", "Operation"]:
return self._expression

@ -1,17 +0,0 @@
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from slither.core.declarations import Function
class ChildFunction:
def __init__(self) -> None:
super().__init__()
self._function = None
def set_function(self, function: "Function") -> None:
self._function = function
@property
def function(self) -> "Function":
return self._function

@ -1,17 +0,0 @@
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from slither.core.declarations import Contract
class ChildInheritance:
def __init__(self) -> None:
super().__init__()
self._contract_declarer = None
def set_contract_declarer(self, contract: "Contract") -> None:
self._contract_declarer = contract
@property
def contract_declarer(self) -> "Contract":
return self._contract_declarer

@ -1,31 +0,0 @@
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from slither.core.compilation_unit import SlitherCompilationUnit
from slither.core.cfg.node import Node
from slither.core.declarations import Function, Contract
class ChildNode:
def __init__(self) -> None:
super().__init__()
self._node = None
def set_node(self, node: "Node") -> None:
self._node = node
@property
def node(self) -> "Node":
return self._node
@property
def function(self) -> "Function":
return self.node.function
@property
def contract(self) -> "Contract":
return self.node.function.contract
@property
def compilation_unit(self) -> "SlitherCompilationUnit":
return self.node.compilation_unit

@ -1,17 +0,0 @@
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from slither.core.declarations import Structure
class ChildStructure:
def __init__(self) -> None:
super().__init__()
self._structure = None
def set_structure(self, structure: "Structure") -> None:
self._structure = structure
@property
def structure(self) -> "Structure":
return self._structure

@ -1,4 +1,4 @@
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Optional
from slither.core.source_mapping.source_mapping import SourceMapping
@ -6,14 +6,21 @@ if TYPE_CHECKING:
from slither.core.declarations import Contract
class ChildContract(SourceMapping):
class ContractLevel(SourceMapping):
"""
This class is used to represent objects that are at the contract level
The opposite is TopLevel
"""
def __init__(self) -> None:
super().__init__()
self._contract = None
self._contract: Optional["Contract"] = None
def set_contract(self, contract: "Contract") -> None:
self._contract = contract
@property
def contract(self) -> "Contract":
assert self._contract
return self._contract

@ -1,8 +1,8 @@
from slither.core.children.child_contract import ChildContract
from slither.core.declarations.contract_level import ContractLevel
from slither.core.declarations.custom_error import CustomError
class CustomErrorContract(CustomError, ChildContract):
class CustomErrorContract(CustomError, ContractLevel):
def is_declared_by(self, contract):
"""
Check if the element is declared by the contract

@ -1,13 +1,13 @@
from typing import TYPE_CHECKING
from slither.core.children.child_contract import ChildContract
from slither.core.declarations.contract_level import ContractLevel
from slither.core.declarations import Enum
if TYPE_CHECKING:
from slither.core.declarations import Contract
class EnumContract(Enum, ChildContract):
class EnumContract(Enum, ContractLevel):
def is_declared_by(self, contract: "Contract") -> bool:
"""
Check if the element is declared by the contract

@ -1,6 +1,6 @@
from typing import List, Tuple, TYPE_CHECKING
from slither.core.children.child_contract import ChildContract
from slither.core.declarations.contract_level import ContractLevel
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.variables.event_variable import EventVariable
@ -8,7 +8,7 @@ if TYPE_CHECKING:
from slither.core.declarations import Contract
class Event(ChildContract, SourceMapping):
class Event(ContractLevel, SourceMapping):
def __init__(self) -> None:
super().__init__()
self._name = None

@ -1,10 +1,9 @@
"""
Function module
"""
from typing import Dict, TYPE_CHECKING, List, Tuple
from typing import Dict, TYPE_CHECKING, List, Tuple, Optional
from slither.core.children.child_contract import ChildContract
from slither.core.children.child_inheritance import ChildInheritance
from slither.core.declarations.contract_level import ContractLevel
from slither.core.declarations import Function
@ -14,9 +13,31 @@ if TYPE_CHECKING:
from slither.core.declarations import Contract
from slither.core.scope.scope import FileScope
from slither.slithir.variables.state_variable import StateIRVariable
from slither.core.compilation_unit import SlitherCompilationUnit
class FunctionContract(Function, ChildContract, ChildInheritance):
class FunctionContract(Function, ContractLevel):
def __init__(self, compilation_unit: "SlitherCompilationUnit") -> None:
super().__init__(compilation_unit)
self._contract_declarer: Optional["Contract"] = None
def set_contract_declarer(self, contract: "Contract") -> None:
self._contract_declarer = contract
@property
def contract_declarer(self) -> "Contract":
"""
Return the contract where this function was declared. Only functions have both a contract, and contract_declarer
This is because we need to have separate representation of the function depending of the contract's context
For example a function calling super.f() will generate different IR depending on the current contract's inheritance
Returns:
The contract where this function was declared
"""
assert self._contract_declarer
return self._contract_declarer
@property
def canonical_name(self) -> str:
"""

@ -1,8 +1,8 @@
from slither.core.children.child_contract import ChildContract
from slither.core.declarations.contract_level import ContractLevel
from slither.core.declarations import Structure
class StructureContract(Structure, ChildContract):
class StructureContract(Structure, ContractLevel):
def is_declared_by(self, contract):
"""
Check if the element is declared by the contract

@ -2,4 +2,8 @@ from slither.core.source_mapping.source_mapping import SourceMapping
class TopLevel(SourceMapping):
pass
"""
This class is used to represent objects that are at the top level
The opposite is ContractLevel
"""

@ -13,7 +13,7 @@ from typing import Optional, Dict, List, Set, Union, Tuple
from crytic_compile import CryticCompile
from crytic_compile.utils.naming import Filename
from slither.core.children.child_contract import ChildContract
from slither.core.declarations.contract_level import ContractLevel
from slither.core.compilation_unit import SlitherCompilationUnit
from slither.core.context.context import Context
from slither.core.declarations import Contract, FunctionContract
@ -206,7 +206,10 @@ class SlitherCore(Context):
isinstance(thing, FunctionContract)
and thing.contract_declarer == thing.contract
)
or (isinstance(thing, ChildContract) and not isinstance(thing, FunctionContract))
or (
isinstance(thing, ContractLevel)
and not isinstance(thing, FunctionContract)
)
):
self._offset_to_objects[definition.filename][offset].add(thing)
@ -224,7 +227,8 @@ class SlitherCore(Context):
and thing.contract_declarer == thing.contract
)
or (
isinstance(thing, ChildContract) and not isinstance(thing, FunctionContract)
isinstance(thing, ContractLevel)
and not isinstance(thing, FunctionContract)
)
):
self._offset_to_objects[definition.filename][offset].add(thing)

@ -1,6 +1,6 @@
from typing import TYPE_CHECKING, Tuple
from slither.core.children.child_contract import ChildContract
from slither.core.declarations.contract_level import ContractLevel
from slither.core.declarations.top_level import TopLevel
from slither.core.solidity_types import Type, ElementaryType
@ -48,7 +48,7 @@ class TypeAliasTopLevel(TypeAlias, TopLevel):
return self.name
class TypeAliasContract(TypeAlias, ChildContract):
class TypeAliasContract(TypeAlias, ContractLevel):
def __init__(self, underlying_type: Type, name: str, contract: "Contract") -> None:
super().__init__(underlying_type, name)
self._contract: "Contract" = contract

@ -1,8 +1,7 @@
from slither.core.variables.variable import Variable
from slither.core.children.child_event import ChildEvent
class EventVariable(ChildEvent, Variable):
class EventVariable(Variable):
def __init__(self) -> None:
super().__init__()
self._indexed = False
@ -16,5 +15,5 @@ class EventVariable(ChildEvent, Variable):
return self._indexed
@indexed.setter
def indexed(self, is_indexed: bool):
def indexed(self, is_indexed: bool) -> None:
self._indexed = is_indexed

@ -1,7 +1,6 @@
from typing import Optional
from typing import Optional, TYPE_CHECKING
from slither.core.variables.variable import Variable
from slither.core.children.child_function import ChildFunction
from slither.core.solidity_types.user_defined_type import UserDefinedType
from slither.core.solidity_types.array_type import ArrayType
from slither.core.solidity_types.mapping_type import MappingType
@ -9,11 +8,23 @@ from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.declarations.structure import Structure
if TYPE_CHECKING: # type: ignore
from slither.core.declarations import Function
class LocalVariable(ChildFunction, Variable):
class LocalVariable(Variable):
def __init__(self) -> None:
super().__init__()
self._location: Optional[str] = None
self._function: Optional["Function"] = None
def set_function(self, function: "Function") -> None:
self._function = function
@property
def function(self) -> "Function":
assert self._function
return self._function
def set_location(self, loc: str) -> None:
self._location = loc

@ -1,6 +1,6 @@
from typing import Optional, TYPE_CHECKING
from slither.core.children.child_contract import ChildContract
from slither.core.declarations.contract_level import ContractLevel
from slither.core.variables.variable import Variable
if TYPE_CHECKING:
@ -8,7 +8,7 @@ if TYPE_CHECKING:
from slither.core.declarations import Contract
class StateVariable(ChildContract, Variable):
class StateVariable(ContractLevel, Variable):
def __init__(self) -> None:
super().__init__()
self._node_initialization: Optional["Node"] = None

@ -1,6 +1,19 @@
from typing import TYPE_CHECKING, Optional
from slither.core.variables.variable import Variable
from slither.core.children.child_structure import ChildStructure
class StructureVariable(ChildStructure, Variable):
pass
if TYPE_CHECKING:
from slither.core.declarations import Structure
class StructureVariable(Variable):
def __init__(self) -> None:
super().__init__()
self._structure: Optional["Structure"] = None
def set_structure(self, structure: "Structure") -> None:
self._structure = structure
@property
def structure(self) -> "Structure":
return self._structure

@ -89,7 +89,9 @@ contract Token{
return False
@staticmethod
def detect_incorrect_erc721_interface(contract: Contract) -> List[Union[FunctionContract, Any]]:
def detect_incorrect_erc721_interface(
contract: Contract,
) -> List[Union[FunctionContract, Any]]:
"""Detect incorrect ERC721 interface
Returns:

@ -70,7 +70,9 @@ contract C {
def _detect_missing_events(
self, contract: Contract
) -> List[Tuple[FunctionContract, List[Tuple[Node, List[Tuple[Node, FunctionContract]]]]]]:
) -> List[
Tuple[FunctionContract, List[Tuple[Node, List[Tuple[Node, FunctionContract]]]]]
]:
"""
Detects if critical contract parameters set by owners and used in arithmetic are missing events
:param contract: The contract to check

@ -57,7 +57,9 @@ Bob is the owner of `TxOrigin`. Bob calls Eve's contract. Eve's contract calls `
)
return False
def detect_tx_origin(self, contract: Contract) -> List[Tuple[FunctionContract, List[Node]]]:
def detect_tx_origin(
self, contract: Contract
) -> List[Tuple[FunctionContract, List[Node]]]:
ret = []
for f in contract.functions:

@ -731,7 +731,7 @@ def propagate_types(
return _convert_type_contract(ir)
left = ir.variable_left
t = None
ir_func = ir.function
ir_func = ir.node.function
# Handling of this.function_name usage
if (
left == SolidityVariable("this")

@ -24,7 +24,7 @@ class InternalDynamicCall(
assert isinstance(function, Variable)
assert is_valid_lvalue(lvalue) or lvalue is None
super().__init__()
self._function = function
self._function: Variable = function
self._function_type = function_type
self._lvalue = lvalue
@ -37,7 +37,7 @@ class InternalDynamicCall(
return self._unroll(self.arguments) + [self.function]
@property
def function(self) -> Union[LocalVariable, LocalIRVariable]:
def function(self) -> Variable:
return self._function
@property

@ -14,7 +14,9 @@ from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
class NewStructure(Call, OperationWithLValue):
def __init__(
self, structure: StructureContract, lvalue: Union[TemporaryVariableSSA, TemporaryVariable]
self,
structure: StructureContract,
lvalue: Union[TemporaryVariableSSA, TemporaryVariable],
) -> None:
super().__init__()
assert isinstance(structure, Structure)

@ -1,11 +1,14 @@
import abc
from typing import Any, List
from typing import Any, List, Optional, TYPE_CHECKING
from slither.core.context.context import Context
from slither.core.children.child_expression import ChildExpression
from slither.core.children.child_node import ChildNode
from slither.core.expressions.expression import Expression
from slither.core.variables.variable import Variable
from slither.utils.utils import unroll
if TYPE_CHECKING:
from slither.core.compilation_unit import SlitherCompilationUnit
from slither.core.cfg.node import Node
class AbstractOperation(abc.ABC):
@property
@ -25,7 +28,24 @@ class AbstractOperation(abc.ABC):
pass # pylint: disable=unnecessary-pass
class Operation(Context, ChildExpression, ChildNode, AbstractOperation):
class Operation(Context, AbstractOperation):
def __init__(self) -> None:
super().__init__()
self._node: Optional["Node"] = None
self._expression: Optional[Expression] = None
def set_node(self, node: "Node") -> None:
self._node = node
@property
def node(self) -> "Node":
assert self._node
return self._node
@property
def compilation_unit(self) -> "SlitherCompilationUnit":
return self.node.compilation_unit
@property
def used(self) -> List[Variable]:
"""
@ -37,3 +57,10 @@ class Operation(Context, ChildExpression, ChildNode, AbstractOperation):
@staticmethod
def _unroll(l: List[Any]) -> List[Any]:
return unroll(l)
def set_expression(self, expression: Expression) -> None:
self._expression = expression
@property
def expression(self) -> Optional[Expression]:
return self._expression

@ -2,7 +2,6 @@ from typing import Any, List, Union
from slither.core.declarations.solidity_variables import SolidityCustomRevert, SolidityFunction
from slither.slithir.operations.call import Call
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.core.children.child_node import ChildNode
from slither.core.solidity_types.elementary_type import ElementaryType
@ -11,7 +10,7 @@ class SolidityCall(Call, OperationWithLValue):
self,
function: Union[SolidityCustomRevert, SolidityFunction],
nbr_arguments: int,
result: ChildNode,
result,
type_call: Union[str, List[ElementaryType]],
) -> None:
assert isinstance(function, SolidityFunction)

@ -17,7 +17,9 @@ class TypeConversion(OperationWithLValue):
self,
result: Union[TemporaryVariableSSA, TemporaryVariable],
variable: SourceMapping,
variable_type: Union[TypeAliasContract, UserDefinedType, ElementaryType, TypeAliasTopLevel],
variable_type: Union[
TypeAliasContract, UserDefinedType, ElementaryType, TypeAliasTopLevel
],
) -> None:
super().__init__()
assert is_valid_rvalue(variable) or isinstance(variable, Contract)

@ -1,6 +1,5 @@
from typing import Optional, TYPE_CHECKING
from slither.core.children.child_node import ChildNode
from slither.core.declarations import Contract, Enum, SolidityVariable, Function
from slither.core.variables.variable import Variable
@ -8,7 +7,7 @@ if TYPE_CHECKING:
from slither.core.cfg.node import Node
class ReferenceVariable(ChildNode, Variable):
class ReferenceVariable(Variable):
def __init__(self, node: "Node", index: Optional[int] = None) -> None:
super().__init__()
if index is None:
@ -19,6 +18,10 @@ class ReferenceVariable(ChildNode, Variable):
self._points_to = None
self._node = node
@property
def node(self) -> "Node":
return self._node
@property
def index(self):
return self._index

@ -1,13 +1,12 @@
from typing import Optional, TYPE_CHECKING
from slither.core.children.child_node import ChildNode
from slither.core.variables.variable import Variable
if TYPE_CHECKING:
from slither.core.cfg.node import Node
class TemporaryVariable(ChildNode, Variable):
class TemporaryVariable(Variable):
def __init__(self, node: "Node", index: Optional[int] = None) -> None:
super().__init__()
if index is None:
@ -17,6 +16,10 @@ class TemporaryVariable(ChildNode, Variable):
self._index = index
self._node = node
@property
def node(self) -> "Node":
return self._node
@property
def index(self):
return self._index

@ -1,13 +1,12 @@
from typing import Optional, TYPE_CHECKING
from slither.core.children.child_node import ChildNode
from slither.slithir.variables.variable import SlithIRVariable
if TYPE_CHECKING:
from slither.core.cfg.node import Node
class TupleVariable(ChildNode, SlithIRVariable):
class TupleVariable(SlithIRVariable):
def __init__(self, node: "Node", index: Optional[int] = None) -> None:
super().__init__()
if index is None:
@ -18,6 +17,10 @@ class TupleVariable(ChildNode, SlithIRVariable):
self._node = node
@property
def node(self) -> "Node":
return self._node
@property
def index(self):
return self._index

@ -2,7 +2,13 @@ import logging
import re
from typing import Any, List, Dict, Callable, TYPE_CHECKING, Union, Set
from slither.core.declarations import Modifier, Event, EnumContract, StructureContract, Function
from slither.core.declarations import (
Modifier,
Event,
EnumContract,
StructureContract,
Function,
)
from slither.core.declarations.contract import Contract
from slither.core.declarations.custom_error_contract import CustomErrorContract
from slither.core.declarations.function_contract import FunctionContract

@ -10,8 +10,17 @@ from zipfile import ZipFile
from pkg_resources import require
from slither.core.cfg.node import Node
from slither.core.declarations import Contract, Function, Enum, Event, Structure, Pragma
from slither.core.declarations import (
Contract,
Function,
Enum,
Event,
Structure,
Pragma,
FunctionContract,
)
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.variable import Variable
from slither.exceptions import SlitherError
from slither.utils.colors import yellow
@ -351,21 +360,19 @@ def _create_parent_element(
],
]:
# pylint: disable=import-outside-toplevel
from slither.core.children.child_contract import ChildContract
from slither.core.children.child_function import ChildFunction
from slither.core.children.child_inheritance import ChildInheritance
from slither.core.declarations.contract_level import ContractLevel
if isinstance(element, ChildInheritance):
if isinstance(element, FunctionContract):
if element.contract_declarer:
contract = Output("")
contract.add_contract(element.contract_declarer)
return contract.data["elements"][0]
elif isinstance(element, ChildContract):
elif isinstance(element, ContractLevel):
if element.contract:
contract = Output("")
contract.add_contract(element.contract)
return contract.data["elements"][0]
elif isinstance(element, ChildFunction):
elif isinstance(element, (LocalVariable, Node)):
if element.function:
function = Output("")
function.add_function(element.function)

@ -689,7 +689,7 @@ def test_initial_version_exists_for_state_variables_function_assign():
# temporary variable, that is then assigned to a
call = get_ssa_of_type(ctor, InternalCall)[0]
assert call.function == f
assert call.node.function == f
assign = get_ssa_of_type(ctor, Assignment)[0]
assert assign.rvalue == call.lvalue
assert isinstance(assign.lvalue, StateIRVariable)

Loading…
Cancel
Save