From ea708cda4f950434804ae05d3cee02146de1f65f Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 20 Oct 2023 08:52:39 -0500 Subject: [PATCH 01/64] remove unused files --- slither/core/children/__init__.py | 0 slither/core/children/child_event.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 slither/core/children/__init__.py delete mode 100644 slither/core/children/child_event.py diff --git a/slither/core/children/__init__.py b/slither/core/children/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/slither/core/children/child_event.py b/slither/core/children/child_event.py deleted file mode 100644 index e69de29bb..000000000 From c1a1675259abf5ebf191176b2176fa6a50b96e2f Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Tue, 24 Oct 2023 18:42:29 +0400 Subject: [PATCH 02/64] added update reachability to modifiers --- slither/solc_parsing/declarations/modifier.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/slither/solc_parsing/declarations/modifier.py b/slither/solc_parsing/declarations/modifier.py index c4c5c7177..77b326945 100644 --- a/slither/solc_parsing/declarations/modifier.py +++ b/slither/solc_parsing/declarations/modifier.py @@ -92,7 +92,9 @@ class ModifierSolc(FunctionSolc): self._rewrite_ternary_as_if_else() self._remove_alone_endif() - + + if self._function.entry_point: + self._update_reachability(self._function.entry_point) # self._analyze_read_write() # self._analyze_calls() From 0994edf110c33723f0f31713c8d5b52a4c90d198 Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Tue, 24 Oct 2023 18:49:05 +0400 Subject: [PATCH 03/64] Update modifier.py removed trailing whitespace --- slither/solc_parsing/declarations/modifier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/solc_parsing/declarations/modifier.py b/slither/solc_parsing/declarations/modifier.py index 77b326945..dfacc8703 100644 --- a/slither/solc_parsing/declarations/modifier.py +++ b/slither/solc_parsing/declarations/modifier.py @@ -92,7 +92,7 @@ class ModifierSolc(FunctionSolc): self._rewrite_ternary_as_if_else() self._remove_alone_endif() - + if self._function.entry_point: self._update_reachability(self._function.entry_point) # self._analyze_read_write() From b7ba2c48da01eded38b20702756d50d2a13e18c7 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 1 Nov 2023 12:12:24 -0500 Subject: [PATCH 04/64] fix is_reentrant for internal vyper functions --- slither/core/declarations/function.py | 13 +++++++++---- tests/unit/core/test_function_declaration.py | 9 ++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index e803154d0..d2baaf7e7 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -1500,10 +1500,13 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu """ Determine if the function can be re-entered """ + reentrancy_modifier = "nonReentrant" + + if self.function_language == FunctionLanguage.Vyper: + reentrancy_modifier = "nonreentrant(lock)" + # TODO: compare with hash of known nonReentrant modifier instead of the name - if "nonReentrant" in [m.name for m in self.modifiers] or "nonreentrant(lock)" in [ - m.name for m in self.modifiers - ]: + if reentrancy_modifier in [m.name for m in self.modifiers]: return False if self.visibility in ["public", "external"]: @@ -1515,7 +1518,9 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu ] if not all_entry_points: return True - return not all(("nonReentrant" in [m.name for m in f.modifiers] for f in all_entry_points)) + return not all( + (reentrancy_modifier in [m.name for m in f.modifiers] for f in all_entry_points) + ) # endregion ################################################################################### diff --git a/tests/unit/core/test_function_declaration.py b/tests/unit/core/test_function_declaration.py index cea207613..f75198d24 100644 --- a/tests/unit/core/test_function_declaration.py +++ b/tests/unit/core/test_function_declaration.py @@ -324,6 +324,9 @@ def withdraw(): @external @nonreentrant("lock") def withdraw_locked(): + self.withdraw_locked_internal() +@internal +def withdraw_locked_internal(): raw_call(msg.sender, b"", value= self.balances[msg.sender]) @payable @external @@ -376,10 +379,14 @@ def __default__(): assert not f.is_empty f = functions["withdraw_locked()"] - assert not f.is_reentrant + assert f.is_reentrant is False assert f.is_implemented assert not f.is_empty + f = functions["withdraw_locked_internal()"] + assert f.is_reentrant is False + assert f.visibility == "internal" + var = contract.get_state_variable_from_name("balances") assert var assert var.solidity_signature == "balances(address)" From 4a3354173818fb4cdf52f6b0aa62df60535fb903 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 6 Nov 2023 19:07:01 +0100 Subject: [PATCH 05/64] Add support top level events --- slither/core/compilation_unit.py | 6 +++++ slither/core/declarations/__init__.py | 2 ++ slither/core/declarations/contract.py | 12 ++++----- slither/core/declarations/event.py | 24 ++--------------- slither/core/declarations/event_contract.py | 25 ++++++++++++++++++ slither/core/declarations/event_top_level.py | 13 +++++++++ slither/core/scope/scope.py | 7 ++++- slither/core/slither_core.py | 2 ++ slither/solc_parsing/declarations/contract.py | 8 +++--- slither/solc_parsing/declarations/event.py | 19 +++++++------ .../solc_parsing/expressions/find_variable.py | 3 +++ .../slither_compilation_unit_solc.py | 11 ++++++++ slither/tools/flattening/flattening.py | 1 + .../vyper_parsing/declarations/contract.py | 4 +-- tests/e2e/solc_parsing/test_ast_parsing.py | 1 + .../event-top-level.sol-0.8.22-compact.zip | Bin 0 -> 2022 bytes .../test_data/event-top-level.sol | 7 +++++ .../event-top-level.sol-0.8.22-compact.json | 5 ++++ 18 files changed, 105 insertions(+), 45 deletions(-) create mode 100644 slither/core/declarations/event_contract.py create mode 100644 slither/core/declarations/event_top_level.py create mode 100644 tests/e2e/solc_parsing/test_data/compile/event-top-level.sol-0.8.22-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/event-top-level.sol create mode 100644 tests/e2e/solc_parsing/test_data/expected/event-top-level.sol-0.8.22-compact.json diff --git a/slither/core/compilation_unit.py b/slither/core/compilation_unit.py index 87853aa34..6221fd8bd 100644 --- a/slither/core/compilation_unit.py +++ b/slither/core/compilation_unit.py @@ -16,6 +16,7 @@ from slither.core.declarations import ( ) from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel from slither.core.declarations.enum_top_level import EnumTopLevel +from slither.core.declarations.event_top_level import EventTopLevel from slither.core.declarations.function_top_level import FunctionTopLevel from slither.core.declarations.structure_top_level import StructureTopLevel from slither.core.declarations.using_for_top_level import UsingForTopLevel @@ -57,6 +58,7 @@ class SlitherCompilationUnit(Context): self.contracts: List[Contract] = [] self._structures_top_level: List[StructureTopLevel] = [] self._enums_top_level: List[EnumTopLevel] = [] + self._events_top_level: List[EventTopLevel] = [] self._variables_top_level: List[TopLevelVariable] = [] self._functions_top_level: List[FunctionTopLevel] = [] self._using_for_top_level: List[UsingForTopLevel] = [] @@ -234,6 +236,10 @@ class SlitherCompilationUnit(Context): def enums_top_level(self) -> List[EnumTopLevel]: return self._enums_top_level + @property + def events_top_level(self) -> List[EventTopLevel]: + return self._events_top_level + @property def variables_top_level(self) -> List[TopLevelVariable]: return self._variables_top_level diff --git a/slither/core/declarations/__init__.py b/slither/core/declarations/__init__.py index f6e902e06..9d727da8e 100644 --- a/slither/core/declarations/__init__.py +++ b/slither/core/declarations/__init__.py @@ -1,6 +1,8 @@ from .contract import Contract from .enum import Enum from .event import Event +from .event_contract import EventContract +from .event_top_level import EventTopLevel from .function import Function from .import_directive import Import from .modifier import Modifier diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 458f951f5..5403d227a 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -33,7 +33,7 @@ if TYPE_CHECKING: from slither.utils.type_helpers import LibraryCallType, HighLevelCallType, InternalCallType from slither.core.declarations import ( Enum, - Event, + EventContract, Modifier, EnumContract, StructureContract, @@ -73,7 +73,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods self._enums: Dict[str, "EnumContract"] = {} self._structures: Dict[str, "StructureContract"] = {} - self._events: Dict[str, "Event"] = {} + self._events: Dict[str, "EventContract"] = {} # map accessible variable from name -> variable # do not contain private variables inherited from contract self._variables: Dict[str, "StateVariable"] = {} @@ -278,28 +278,28 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods ################################################################################### @property - def events(self) -> List["Event"]: + def events(self) -> List["EventContract"]: """ list(Event): List of the events """ return list(self._events.values()) @property - def events_inherited(self) -> List["Event"]: + def events_inherited(self) -> List["EventContract"]: """ list(Event): List of the inherited events """ return [e for e in self.events if e.contract != self] @property - def events_declared(self) -> List["Event"]: + def events_declared(self) -> List["EventContract"]: """ list(Event): List of the events declared within the contract (not inherited) """ return [e for e in self.events if e.contract == self] @property - def events_as_dict(self) -> Dict[str, "Event"]: + def events_as_dict(self) -> Dict[str, "EventContract"]: return self._events # endregion diff --git a/slither/core/declarations/event.py b/slither/core/declarations/event.py index 1b58ff63b..7149e20c0 100644 --- a/slither/core/declarations/event.py +++ b/slither/core/declarations/event.py @@ -1,14 +1,10 @@ -from typing import List, Tuple, TYPE_CHECKING +from typing import List, Tuple -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 -if TYPE_CHECKING: - from slither.core.declarations import Contract - -class Event(ContractLevel, SourceMapping): +class Event(SourceMapping): def __init__(self) -> None: super().__init__() self._name = None @@ -39,25 +35,9 @@ class Event(ContractLevel, SourceMapping): name, parameters = self.signature return name + "(" + ",".join(parameters) + ")" - @property - def canonical_name(self) -> str: - """Return the function signature as a str - Returns: - str: contract.func_name(type1,type2) - """ - return self.contract.name + "." + self.full_name - @property def elems(self) -> List["EventVariable"]: return self._elems - def is_declared_by(self, contract: "Contract") -> bool: - """ - Check if the element is declared by the contract - :param contract: - :return: - """ - return self.contract == contract - def __str__(self) -> str: return self.name diff --git a/slither/core/declarations/event_contract.py b/slither/core/declarations/event_contract.py new file mode 100644 index 000000000..652f8ca20 --- /dev/null +++ b/slither/core/declarations/event_contract.py @@ -0,0 +1,25 @@ +from typing import TYPE_CHECKING + +from slither.core.declarations.contract_level import ContractLevel +from slither.core.declarations import Event + +if TYPE_CHECKING: + from slither.core.declarations import Contract + + +class EventContract(Event, ContractLevel): + def is_declared_by(self, contract: "Contract") -> bool: + """ + Check if the element is declared by the contract + :param contract: + :return: + """ + return self.contract == contract + + @property + def canonical_name(self) -> str: + """Return the function signature as a str + Returns: + str: contract.func_name(type1,type2) + """ + return self.contract.name + "." + self.full_name diff --git a/slither/core/declarations/event_top_level.py b/slither/core/declarations/event_top_level.py new file mode 100644 index 000000000..5f9f1774d --- /dev/null +++ b/slither/core/declarations/event_top_level.py @@ -0,0 +1,13 @@ +from typing import TYPE_CHECKING + +from slither.core.declarations import Event +from slither.core.declarations.top_level import TopLevel + +if TYPE_CHECKING: + from slither.core.scope.scope import FileScope + + +class EventTopLevel(Event, TopLevel): + def __init__(self, scope: "FileScope") -> None: + super().__init__() + self.file_scope: "FileScope" = scope diff --git a/slither/core/scope/scope.py b/slither/core/scope/scope.py index 937a05136..784b17cb2 100644 --- a/slither/core/scope/scope.py +++ b/slither/core/scope/scope.py @@ -7,6 +7,7 @@ from crytic_compile.utils.naming import Filename from slither.core.declarations import Contract, Import, Pragma from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel from slither.core.declarations.enum_top_level import EnumTopLevel +from slither.core.declarations.event_top_level import EventTopLevel from slither.core.declarations.function_top_level import FunctionTopLevel from slither.core.declarations.using_for_top_level import UsingForTopLevel from slither.core.declarations.structure_top_level import StructureTopLevel @@ -35,6 +36,7 @@ class FileScope: # So we simplify the logic and have the scope fields all populated self.custom_errors: Set[CustomErrorTopLevel] = set() self.enums: Dict[str, EnumTopLevel] = {} + self.events: Dict[str, EventTopLevel] = {} # Functions is a list instead of a dict # Because we parse the function signature later on # So we simplify the logic and have the scope fields all populated @@ -54,7 +56,7 @@ class FileScope: # Name -> type alias self.type_aliases: Dict[str, TypeAlias] = {} - def add_accesible_scopes(self) -> bool: + def add_accesible_scopes(self) -> bool: # pylint: disable=too-many-branches """ Add information from accessible scopes. Return true if new information was obtained @@ -74,6 +76,9 @@ class FileScope: if not _dict_contain(new_scope.enums, self.enums): self.enums.update(new_scope.enums) learn_something = True + if not _dict_contain(new_scope.events, self.events): + self.events.update(new_scope.events) + learn_something = True if not new_scope.functions.issubset(self.functions): self.functions |= new_scope.functions learn_something = True diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py index 3535f2604..b1bb7c66b 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -269,6 +269,8 @@ class SlitherCore(Context): self._compute_offsets_from_thing(event) for enum in compilation_unit.enums_top_level: self._compute_offsets_from_thing(enum) + for event in compilation_unit.events_top_level: + self._compute_offsets_from_thing(event) for function in compilation_unit.functions_top_level: self._compute_offsets_from_thing(function) for st in compilation_unit.structures_top_level: diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py index 3dd6e2fd5..34e2f2430 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -4,7 +4,7 @@ from typing import Any, List, Dict, Callable, TYPE_CHECKING, Union, Set, Sequenc from slither.core.declarations import ( Modifier, - Event, + EventContract, EnumContract, StructureContract, Function, @@ -747,12 +747,12 @@ class ContractSolc(CallerContextExpression): self._contract.events_as_dict.update(father.events_as_dict) for event_to_parse in self._eventsNotParsed: - event = Event() + event = EventContract() event.set_contract(self._contract) event.set_offset(event_to_parse["src"], self._contract.compilation_unit) - event_parser = EventSolc(event, event_to_parse, self) # type: ignore - event_parser.analyze(self) # type: ignore + event_parser = EventSolc(event, event_to_parse, self._slither_parser) # type: ignore + event_parser.analyze() # type: ignore self._contract.events_as_dict[event.full_name] = event except (VariableNotFound, KeyError) as e: self.log_incorrect_parsing(f"Missing event {e}") diff --git a/slither/solc_parsing/declarations/event.py b/slither/solc_parsing/declarations/event.py index 6531e6536..4a7d62389 100644 --- a/slither/solc_parsing/declarations/event.py +++ b/slither/solc_parsing/declarations/event.py @@ -8,7 +8,7 @@ from slither.solc_parsing.variables.event_variable import EventVariableSolc from slither.core.declarations.event import Event if TYPE_CHECKING: - from slither.solc_parsing.declarations.contract import ContractSolc + from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc class EventSolc: @@ -16,11 +16,12 @@ class EventSolc: Event class """ - def __init__(self, event: Event, event_data: Dict, contract_parser: "ContractSolc") -> None: + def __init__( + self, event: Event, event_data: Dict, slither_parser: "SlitherCompilationUnitSolc" + ) -> None: self._event = event - event.set_contract(contract_parser.underlying_contract) - self._parser_contract = contract_parser + self._slither_parser = slither_parser if self.is_compact_ast: self._event.name = event_data["name"] @@ -41,18 +42,16 @@ class EventSolc: @property def is_compact_ast(self) -> bool: - return self._parser_contract.is_compact_ast + return self._slither_parser.is_compact_ast - def analyze(self, contract: "ContractSolc") -> None: + def analyze(self) -> None: for elem_to_parse in self._elemsNotParsed: elem = EventVariable() # Todo: check if the source offset is always here if "src" in elem_to_parse: - elem.set_offset( - elem_to_parse["src"], self._parser_contract.underlying_contract.compilation_unit - ) + elem.set_offset(elem_to_parse["src"], self._slither_parser.compilation_unit) elem_parser = EventVariableSolc(elem, elem_to_parse) - elem_parser.analyze(contract) + elem_parser.analyze(self._slither_parser) self._event.elems.append(elem) diff --git a/slither/solc_parsing/expressions/find_variable.py b/slither/solc_parsing/expressions/find_variable.py index 2261350b4..e7fa99521 100644 --- a/slither/solc_parsing/expressions/find_variable.py +++ b/slither/solc_parsing/expressions/find_variable.py @@ -134,6 +134,9 @@ def find_top_level( if var_name in scope.enums: return scope.enums[var_name], False + if var_name in scope.events: + return scope.events[var_name], False + for import_directive in scope.imports: if import_directive.alias == var_name: new_val = SolidityImportPlaceHolder(import_directive) diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 85921ce74..08ee62d80 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -10,6 +10,7 @@ from slither.core.compilation_unit import SlitherCompilationUnit from slither.core.declarations import Contract from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel from slither.core.declarations.enum_top_level import EnumTopLevel +from slither.core.declarations.event_top_level import EventTopLevel from slither.core.declarations.function_top_level import FunctionTopLevel from slither.core.declarations.import_directive import Import from slither.core.declarations.pragma_directive import Pragma @@ -23,6 +24,7 @@ from slither.solc_parsing.declarations.caller_context import CallerContextExpres from slither.solc_parsing.declarations.contract import ContractSolc from slither.solc_parsing.declarations.custom_error import CustomErrorSolc from slither.solc_parsing.declarations.function import FunctionSolc +from slither.solc_parsing.declarations.event import EventSolc from slither.solc_parsing.declarations.structure_top_level import StructureTopLevelSolc from slither.solc_parsing.declarations.using_for_top_level import UsingForTopLevelSolc from slither.solc_parsing.exceptions import VariableNotFound @@ -347,6 +349,15 @@ class SlitherCompilationUnitSolc(CallerContextExpression): self._compilation_unit.type_aliases[alias] = type_alias scope.type_aliases[alias] = type_alias + elif top_level_data[self.get_key()] == "EventDefinition": + event = EventTopLevel(scope) + event.set_offset(top_level_data["src"], self._compilation_unit) + + event_parser = EventSolc(event, top_level_data, self) # type: ignore + event_parser.analyze() # type: ignore + scope.events[event.full_name] = event + self._compilation_unit.events_top_level.append(event) + else: raise SlitherException(f"Top level {top_level_data[self.get_key()]} not supported") diff --git a/slither/tools/flattening/flattening.py b/slither/tools/flattening/flattening.py index 55e1af21d..9cb2abc3f 100644 --- a/slither/tools/flattening/flattening.py +++ b/slither/tools/flattening/flattening.py @@ -77,6 +77,7 @@ class Flattening: self._get_source_code_top_level(compilation_unit.structures_top_level) self._get_source_code_top_level(compilation_unit.enums_top_level) + self._get_source_code_top_level(compilation_unit.events_top_level) self._get_source_code_top_level(compilation_unit.custom_errors) self._get_source_code_top_level(compilation_unit.variables_top_level) self._get_source_code_top_level(compilation_unit.functions_top_level) diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index 6ca9c6557..2acd43e0f 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -24,7 +24,7 @@ from slither.vyper_parsing.declarations.struct import StructVyper from slither.vyper_parsing.variables.state_variable import StateVariableVyper from slither.vyper_parsing.declarations.function import FunctionVyper from slither.core.declarations.function_contract import FunctionContract -from slither.core.declarations import Contract, StructureContract, EnumContract, Event +from slither.core.declarations import Contract, StructureContract, EnumContract, EventContract from slither.core.variables.state_variable import StateVariable @@ -478,7 +478,7 @@ class ContractVyper: # pylint: disable=too-many-instance-attributes def parse_events(self) -> None: for event_to_parse in self._eventsNotParsed: - event = Event() + event = EventContract() event.set_contract(self._contract) event.set_offset(event_to_parse.src, self._contract.compilation_unit) diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index bc57dc51b..61250c5af 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -462,6 +462,7 @@ ALL_TESTS = [ Test("aliasing/main.sol", ["0.8.19"]), Test("type-aliases.sol", ["0.8.19"]), Test("enum-max-min.sol", ["0.8.19"]), + Test("event-top-level.sol", ["0.8.22"]), ] # create the output folder if needed try: diff --git a/tests/e2e/solc_parsing/test_data/compile/event-top-level.sol-0.8.22-compact.zip b/tests/e2e/solc_parsing/test_data/compile/event-top-level.sol-0.8.22-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..ed82f32b17350e7c70788a8d84e0d02dcbdd0bba GIT binary patch literal 2022 zcma)-c{~#g1IIUHBvRzQkBl7kxX+C!SMey@=wMb@=4#_*Dw2uHk;r1sZ02mt$K)J^ zJaXo~>SbcC=2}zX>3RQuKcDCK`{Vojfd zXaN9#+mW|JaC*4VFg?ugiP6V~Vtj5#g@xY5`5^D20@0DT_3vOqLxcs60B!&PaR7jI zQc{57FT?Pn;r@C{QBr3JTC+`wkm4a{qdbmnkvg|~-X?Wg9(iJ6v0+ODmY=rkD7Q^B z@Yo<`JC=%1j^M)cLWElT-iH$~#WgRhfD>{y@wY5PR!$A6W#mR@5x?!{3n$Pf(q(ae zFZxWjJ0JXY?vd!jL!t`1j6Q;6GHAVqfy@SWXC{%qVRL7K^&AmqPH%+aRUZ6$HhQ-! z0#!ZnV@g86a;9kisRHacvMt$8YPz;?{yk@?hW)NV1X@V$ZU!d4i}dLidRv2t8xF%m z&~W{*KfzG;#CLnr73^S76S*1~Up7H`;XP$TZh|9(lhGq=kMO%%RsIZNy$Ck=VUkQ0 z@n$UiG=_O}j8U_?n2Z0;+EuD~w{5hrrzB+Dg8Evo&QM>y=AA?##NzJASxl2m``V$g z)Q5}Rm0jj<-FInXD=tj68+{eM$_}}@?i0Q{f{)&x)za?DoE3_@NPrfaUCNS-%wvjd z>Udv2@99SwJCY+rcaPna9I)oea`AjIYnqX-tHUc8!u?I4*RDT-*03VMijMhG9XWyF zjP6+Hn{6|9zB#3*n9VIsqsPK87WO zN|*I?x145$+l`7Ye^Ge4Y)6S3H)rT_6?t(g^s2xaz8xJH(rtmI2-z=cR3@5D;Jdsb@dk+>2veK1M68klnfl-FkQ&Oc9La`GDCS4>n2@ z*pMJ-R9~U)kp?K4Lzc@KpHGJVT+9#_bzz^17MM4L`fY{9Hg`(XqM||fwy-|U5$tH| zf)OwHF;X&T&$ae1h@-<0`b5%aP<$Dii}{*SnWo5DA@;j~NM_`0Y) z%4h9qHtT?{8Wt?aCbxF-*NfmrJ%Zo#?}{eIwxoRVag8hg zqm|Jtx35W?|B$NaS}h6=KaqEQ)M3B(eErpeH``zht4U}($)L~d^Tk^4m(EYCmrdt) z((S0|I;e5BqTyKwN{Q(e1xI%oLSX~s`0`}L!i3nmvgL(N3w(rp>ENVAm=eFUmK{6@ z?KR}DEpy$8^GI5|72J5#3zof`)}h`bIjZVdSn#C^%XBv_Ji4?Iz36yr(KarNx8)Tv ztRfSC8n)eFUdJ1{29dfN)68dCkV;;=XRj%Fp6eVB)kF_zy!{!$5OeP-OelCY{ z%>j<`y)XozR&dekLNE#4nIY3qcj#0L%h8E4f)rQ=!}cisL@-lbL@S_M*`sb z>3)VO{p%b=m)c7|2jhkbG7P>EC;kjq9R3V2>e!RBQvS7^!nbtMPU+px)GRJ{|1!Z0 z4UN0bD+L9uzl|58#(_JzOPC~7HjW@3QB1sIf=Xj|2ymu;J}F)_y}_o7^!MPaWsSe96{95a5R z`5pFM$H-Rp1$~_ciG77b{e< z-6*P8?qynzlHZhePUxkpDpLsqxl!mAkjXQT5_dc~c>M{!^HgeQ#RZL+w4&13ry9C9&cY$YpFh@5{i+eq(;T1~N-!^45| zi>&pP3h%|~0l$vG|B{3UoKh=TO#Sxm{srI(wm7BppwbJ0v0|HD9wVD8aofC2N#oH> zpoZG6h?wfx^IGq`aw5{fb_io!27jt$RY;Ehj`yTvY00EydFu!8Uch^MxUq4KEiVnr zAP3Q%x@W6AZv^59_8JKu+-?S0GsV7({UG6t>QJRDhd0=i9RAkd`8Coj!Fr$QORa?@ zYm4cx$8uh#3R0`orJ@FjFP^{d)+^FbK+zY(50ZT_yUaT|!!+WwsG#Ah*0^e>sXigGw(QRz4Q?Dr+TD6*Z8DpEH~` p-Cclu5dQx!-{1cIU*drO;9siP-Q|ejKX>5odj4k2Z<_-Ee*>9z)$#xU literal 0 HcmV?d00001 diff --git a/tests/e2e/solc_parsing/test_data/event-top-level.sol b/tests/e2e/solc_parsing/test_data/event-top-level.sol new file mode 100644 index 000000000..fa64e1bf7 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/event-top-level.sol @@ -0,0 +1,7 @@ +event MyEvent(uint256 a); + +contract T { + function a() public { + emit MyEvent(2); + } +} diff --git a/tests/e2e/solc_parsing/test_data/expected/event-top-level.sol-0.8.22-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-top-level.sol-0.8.22-compact.json new file mode 100644 index 000000000..58c6a3ab6 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/event-top-level.sol-0.8.22-compact.json @@ -0,0 +1,5 @@ +{ + "T": { + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file From a793c3f1b9f364e0062b6203e04c1a93bac8e164 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 20 Nov 2023 11:43:31 +0100 Subject: [PATCH 06/64] Don't report if msg.value is in a conditional expression --- .../detectors/statements/msg_value_in_loop.py | 18 ++++++++++ .../msg-value-loop/0.4.25/msg_value_loop.sol | 34 ++++++++++++++++++ .../0.4.25/msg_value_loop.sol-0.4.25.zip | Bin 3539 -> 5783 bytes .../msg-value-loop/0.5.16/msg_value_loop.sol | 34 ++++++++++++++++++ .../0.5.16/msg_value_loop.sol-0.5.16.zip | Bin 3834 -> 6192 bytes .../msg-value-loop/0.6.11/msg_value_loop.sol | 34 ++++++++++++++++++ .../0.6.11/msg_value_loop.sol-0.6.11.zip | Bin 3668 -> 5980 bytes .../msg-value-loop/0.7.6/msg_value_loop.sol | 34 ++++++++++++++++++ .../0.7.6/msg_value_loop.sol-0.7.6.zip | Bin 3593 -> 5820 bytes .../msg-value-loop/0.8.0/msg_value_loop.sol | 34 ++++++++++++++++++ .../0.8.0/msg_value_loop.sol-0.8.0.zip | Bin 4647 -> 6854 bytes 11 files changed, 188 insertions(+) diff --git a/slither/detectors/statements/msg_value_in_loop.py b/slither/detectors/statements/msg_value_in_loop.py index 83c5658ca..290447aa8 100644 --- a/slither/detectors/statements/msg_value_in_loop.py +++ b/slither/detectors/statements/msg_value_in_loop.py @@ -8,6 +8,9 @@ from slither.detectors.abstract_detector import ( from slither.slithir.operations import InternalCall from slither.core.declarations import SolidityVariableComposed, Contract from slither.utils.output import Output +from slither.slithir.variables.constant import Constant +from slither.core.variables import Variable +from slither.core.expressions.literal import Literal def detect_msg_value_in_loop(contract: Contract) -> List[Node]: @@ -37,6 +40,21 @@ def msg_value_in_loop( for ir in node.all_slithir_operations(): if in_loop_counter > 0 and SolidityVariableComposed("msg.value") in ir.read: + # If we find a conditional expression with msg.value and is compared to 0 we don't report it + if ir.node.is_conditional() and SolidityVariableComposed("msg.value") in ir.read: + compared_to = ( + ir.read[1] + if ir.read[0] == SolidityVariableComposed("msg.value") + else ir.read[0] + ) + if ( + isinstance(compared_to, Constant) + and compared_to.value == 0 + or isinstance(compared_to, Variable) + and isinstance(compared_to.expression, Literal) + and str(compared_to.expression.value) == "0" + ): + continue results.append(ir.node) if isinstance(ir, (InternalCall)): msg_value_in_loop(ir.function.entry_point, in_loop_counter, visited, results) diff --git a/tests/e2e/detectors/test_data/msg-value-loop/0.4.25/msg_value_loop.sol b/tests/e2e/detectors/test_data/msg-value-loop/0.4.25/msg_value_loop.sol index a32b79d8d..e0f35861a 100644 --- a/tests/e2e/detectors/test_data/msg-value-loop/0.4.25/msg_value_loop.sol +++ b/tests/e2e/detectors/test_data/msg-value-loop/0.4.25/msg_value_loop.sol @@ -26,4 +26,38 @@ contract C{ } } + function good1(address[] memory receivers) public payable { + require(msg.value == 0); + for (uint256 i = 0; i < receivers.length; i++) { + balances[receivers[i]] += 1; + } + } + + function good2(address[] memory receivers) public payable { + uint zero = 0; + for (uint256 i = 0; i < receivers.length; i++) { + assert(msg.value == zero); + balances[receivers[i]] += 1; + } + } + + function good3(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + if (0 != msg.value) { + revert(); + } + balances[receivers[i]] += 1; + } + } + + function good4(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + _g(); + balances[receivers[i]] += 1; + } + } + + function _g() internal { + require(msg.value == 0); + } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/msg-value-loop/0.4.25/msg_value_loop.sol-0.4.25.zip b/tests/e2e/detectors/test_data/msg-value-loop/0.4.25/msg_value_loop.sol-0.4.25.zip index 377d24cfd8e038962a045fae95fadf5d88d0da35..afa475f85458e82bcb379a3d671b7cec422a053d 100644 GIT binary patch delta 5683 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 Zu&Pk$1{DAR2_ylNgbhgsEfxR(002`4=g|NF delta 3421 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 diff --git a/tests/e2e/detectors/test_data/msg-value-loop/0.5.16/msg_value_loop.sol b/tests/e2e/detectors/test_data/msg-value-loop/0.5.16/msg_value_loop.sol index a32b79d8d..e0f35861a 100644 --- a/tests/e2e/detectors/test_data/msg-value-loop/0.5.16/msg_value_loop.sol +++ b/tests/e2e/detectors/test_data/msg-value-loop/0.5.16/msg_value_loop.sol @@ -26,4 +26,38 @@ contract C{ } } + function good1(address[] memory receivers) public payable { + require(msg.value == 0); + for (uint256 i = 0; i < receivers.length; i++) { + balances[receivers[i]] += 1; + } + } + + function good2(address[] memory receivers) public payable { + uint zero = 0; + for (uint256 i = 0; i < receivers.length; i++) { + assert(msg.value == zero); + balances[receivers[i]] += 1; + } + } + + function good3(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + if (0 != msg.value) { + revert(); + } + balances[receivers[i]] += 1; + } + } + + function good4(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + _g(); + balances[receivers[i]] += 1; + } + } + + function _g() internal { + require(msg.value == 0); + } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/msg-value-loop/0.5.16/msg_value_loop.sol-0.5.16.zip b/tests/e2e/detectors/test_data/msg-value-loop/0.5.16/msg_value_loop.sol-0.5.16.zip index e6082623ef1d01beac56c51a38b7ec847d548e51..2089eb4335bc830c98042941fe71c920fdd39c1e 100644 GIT binary patch delta 6095 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 Vf)@Y)qc{PRs}4y9#uoqp000VCvAh5P delta 3724 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 diff --git a/tests/e2e/detectors/test_data/msg-value-loop/0.6.11/msg_value_loop.sol b/tests/e2e/detectors/test_data/msg-value-loop/0.6.11/msg_value_loop.sol index a32b79d8d..e0f35861a 100644 --- a/tests/e2e/detectors/test_data/msg-value-loop/0.6.11/msg_value_loop.sol +++ b/tests/e2e/detectors/test_data/msg-value-loop/0.6.11/msg_value_loop.sol @@ -26,4 +26,38 @@ contract C{ } } + function good1(address[] memory receivers) public payable { + require(msg.value == 0); + for (uint256 i = 0; i < receivers.length; i++) { + balances[receivers[i]] += 1; + } + } + + function good2(address[] memory receivers) public payable { + uint zero = 0; + for (uint256 i = 0; i < receivers.length; i++) { + assert(msg.value == zero); + balances[receivers[i]] += 1; + } + } + + function good3(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + if (0 != msg.value) { + revert(); + } + balances[receivers[i]] += 1; + } + } + + function good4(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + _g(); + balances[receivers[i]] += 1; + } + } + + function _g() internal { + require(msg.value == 0); + } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/msg-value-loop/0.6.11/msg_value_loop.sol-0.6.11.zip b/tests/e2e/detectors/test_data/msg-value-loop/0.6.11/msg_value_loop.sol-0.6.11.zip index 2aeae50e8626a70381e92b464f7c3c47624222cc..fe0c5241cb7f1297768685d9e80575b9194acf54 100644 GIT binary patch delta 5881 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 H00000;gPXE diff --git a/tests/e2e/detectors/test_data/msg-value-loop/0.8.0/msg_value_loop.sol b/tests/e2e/detectors/test_data/msg-value-loop/0.8.0/msg_value_loop.sol index a32b79d8d..e0f35861a 100644 --- a/tests/e2e/detectors/test_data/msg-value-loop/0.8.0/msg_value_loop.sol +++ b/tests/e2e/detectors/test_data/msg-value-loop/0.8.0/msg_value_loop.sol @@ -26,4 +26,38 @@ contract C{ } } + function good1(address[] memory receivers) public payable { + require(msg.value == 0); + for (uint256 i = 0; i < receivers.length; i++) { + balances[receivers[i]] += 1; + } + } + + function good2(address[] memory receivers) public payable { + uint zero = 0; + for (uint256 i = 0; i < receivers.length; i++) { + assert(msg.value == zero); + balances[receivers[i]] += 1; + } + } + + function good3(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + if (0 != msg.value) { + revert(); + } + balances[receivers[i]] += 1; + } + } + + function good4(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + _g(); + balances[receivers[i]] += 1; + } + } + + function _g() internal { + require(msg.value == 0); + } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/msg-value-loop/0.8.0/msg_value_loop.sol-0.8.0.zip b/tests/e2e/detectors/test_data/msg-value-loop/0.8.0/msg_value_loop.sol-0.8.0.zip index 13d17a8aa06963b37222efbc6472a2c40d44a7cf..5eb9b1fceb1fc04c8e81864c96dd811480379f89 100644 GIT binary patch delta 6762 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 M5lIGI8UO$Q0K%~x$p8QV delta 4538 zcmV;r5k>CCHK!yQP)h>@KL7#%4ggGzcUDi7a+-M&000?`0FfD0fAL2Tg{75VSJ!(0 z5OMDn=$jD3rR6|_6eqkz(!KsKMyKJHUIlueGO?|fN5_Vob;!aCrhhBff464b7rL==&I^%Mwy$^@k3KOknmZC_SRIMxceCvFObD4}cJH~~ zb)^J+=bhqgj3*5(DI|0GPppM7T=3?wdZD~B zGS-6CAuAU}3AMRx`rljA!jczg;AqWgzL7*jnj9LgEe-6SOa){A9fFY&Z9#vIAzt=xCkX64n zW85#ADI1PVb6nDQ7$^@`3Py1qG7cs>!(k@IVpAyZX%LSbq#Sa?t z3A5)oEs`D4kpvl@PZ~mb{soTK;3!ZLcqTAJdQ}_hbZq6 zgIup6UFVff1J~~^z^aaYxdbEnaS=X1e-!BEwGbh(sAK6fFtjvMQywf&b8$KMXzbdF zSo?2u9)aI#8KWA$JBee@s4x zlS*K~)RpD|$wHIuSaZJG&Fli0XaNyHd5Bnn&& zGJV1xSFSnTq92EMVCyt*+G@m1XOJ%kCRT#Rwyo>uJ~W`esOxhJcRcHC+%Komek2)| zrJo&&!47Z__+cY~wS`rvF-B63h)d6-K$jhDrDdG2ipd^21}h+6uns*Ie}O`;q=qAX z=H4CBx(Kn&mNaRbJyIjfA<8Q6r6RJ-R98eI!o9cKS~>tG;Y%Kg*ytT6^w6OhXXFn$ zy{Kv|)Nb6%l0FHf(wtKdor z%5gZ-7|o_;Y>>Jwjbv}5fAO}-{7h^Hg}+28t>av0)FB4@Usc!;dZC8BS%`ONBCT?K;HFoawGtTVsR)qMH^n(C) z4USwZRUzHPBvuu)_`oC906f3EGEK?~eIEp#Lk9~wJG{v?e_^otA@Nj7Fu4PH-Jk4V z3R(OX=-24i%~xU%REZ_`ypB2~2eR@C$@>XA$Ql~T5N+hSU z*GSLOU;YEKCJKV==L!$0X7s^ND&7u`520>(7R0JzGGRV&Z{x(W=G``voO7*i>)!% zj*16Z2~rl|#aHkmzw=cyvadyxkScA!wT>$x5)x3;TdK02@X&G1|1Se9%(hiizG{>#7hPeatA zt{&_@Hcx-c8RGqyEZD0xoLJ=S+;yROGn2YuNwn&Q)dFDQtL_&r#%Hx(5$8WCtpHpy zsgnjpe^{RhRl|)djBLU86vz>QR~OSIif%-Ou8*8^M@V(78*_FO(RCKWEKwu4AZgWStlsDCfik_HSin78KX5_WR8pnJuPz z-IsPL%ZU|Wo#zQcXe{%azS%#Ldt}X*%|C#&XsBUXcmwud^ zvrTWGNVL>HOfY9z6{|)ZfQ!A9`r`4p=U{R#Ld249a2|oUAtgsz{uQ<`MT{lsS1H6s zBkm+cJ5!!SVu^*ZY2Ncd5?s6<%PWM>r-l%jEU4GPNYoL#8v$xyKxR^-BcMsY+-d)+tw#dvrDFp+#gNU{KVuBn1d7y{b8H4S*|J+AWd5y9zRCDB3*^^P*e?C{&R?XQ{0k^xUYmb`#7bRl~&l=D{UfM`d zL%~lHCUm-Ne1<^7^y2c+^qi;wLc^;%tsJ&G#%dWIE3!xsp$YM^W)V4FZG2_bKj+g9 z4z`wPihNxbFZ+%??wihvQ`PnK@(BtTfvd;jIPz>s@tny{7b_8kY+Kn9)@#Uaf4~?4 zYUmWo#T+fNkeE_AX6#al+Cp|ioW5QW65(Xuv0t9Wj#;^fHUZp0@wP#l7X*)mOIxAz zA>%;oHiw7Ps_O7DPU^S_gS)%B1bQCy5L+Rj{UerN>ePcHd z)M=C=f&ojBBBqpfa9+Q?-YL^W2%+jH8oxo`%^)Id=$zWb>hcN7fhXggsL$vS3W47# zOxx>~W1X+U;a_dgjnNm`_+!4d z(cbXuF5i*du2vaU!jSO81Ae&VHk=%~wB(hT^FMPI(cGS7QYG#Z$DcPli%Z0{<|LyX z=!IzR)|7zzG@Ro8e|aBw0)X)HY&O+II|S+TosA+5LEvIRm?Wg?f&F|z){#)O*A2u8 zwm#$>_+7=zQD6yVWkD3O7WI2k8EFmzxUNauhO85N7`DJEFPU83X1^oWZ!5xN$)uT0M=oJy93Qr3GiJS__;5DvimZz5V ziB2A4)kscX-55I>C+i^Of(?`-Bvz&2C^q=ab`LC+8mRDriMwAh;spu3lzI4?=YVyP z=+CvBlXw2Te~uvWZE%Bsz+h$)H{I<>&=8N2DL@Sj1TE5z`FQFUk0`?i?k@hc4_~bc zu;=M^+s|+mh1WV_lgc+?KTpvKRrL1LofR)G^MbGhpmtLO%3))42<9OHx6ZMq7#F)R zyHw#i4Oj>M%5CmC-d>kq_SRNMW~#T#us%dvbWWfWf1zExzzd;+F2Yv&{yMd^!y0|c z4(Rqm2$2bTjT&+$AIVL`0d1!wF10V49q)%aNX9)t@o1)1o~I{6TwL{eBNK%+HV4p* zdbj`UmIXLX>;Bb8I#va)W-O-4)jJ#a6O4qg!I?hiq3zF-uR9=GNNE@mH1j~9>8?)CZ)RD=?|}DLujjfQ?R#xl3Zxzz`2UprG%CI8oXSOWAn~p`@2`ib%5C{UcE!|E{}t00D1?PdyI-VW zl_{YLn97-y02{)LVYcU44y(#)uK9Suv}-=s Date: Mon, 4 Dec 2023 22:43:16 +0000 Subject: [PATCH 07/64] Bump cachix/install-nix-action from 23 to 24 Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 23 to 24. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/v23...v24) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f04436bd3..4a646bb42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: - name: Set up nix if: matrix.type == 'dapp' - uses: cachix/install-nix-action@v23 + uses: cachix/install-nix-action@v24 - name: Set up cachix if: matrix.type == 'dapp' From 4673fdae7f74a384d4f95a84ea67380bf69396b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:43:18 +0000 Subject: [PATCH 08/64] Bump actions/configure-pages from 3 to 4 Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 3 to 4. - [Release notes](https://github.com/actions/configure-pages/releases) - [Commits](https://github.com/actions/configure-pages/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/configure-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 29356c0c6..d92e5b091 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -30,7 +30,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Setup Pages - uses: actions/configure-pages@v3 + uses: actions/configure-pages@v4 - uses: actions/setup-python@v4 with: python-version: '3.8' From 11def5d607b2a5aee7f7b15484079c1d7f9a39e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:43:22 +0000 Subject: [PATCH 09/64] Bump actions/deploy-pages from 2 to 3 Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 2 to 3. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 29356c0c6..eca7ef0b2 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -43,4 +43,4 @@ jobs: path: './html/' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 + uses: actions/deploy-pages@v3 From 9b74e214eb6e8cdca21bb45f009c0fe47e912178 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:43:26 +0000 Subject: [PATCH 10/64] Bump pypa/gh-action-pypi-publish from 1.8.10 to 1.8.11 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.10 to 1.8.11. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.10...v1.8.11) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7b4d61e89..e0ab4b543 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -44,7 +44,7 @@ jobs: path: dist/ - name: publish - uses: pypa/gh-action-pypi-publish@v1.8.10 + uses: pypa/gh-action-pypi-publish@v1.8.11 - name: sign uses: sigstore/gh-action-sigstore-python@v2.1.0 From ff0e85d2c11203985924557ba848c861fc30cc3d Mon Sep 17 00:00:00 2001 From: Atreay Kukanur <66585295+ATREAY@users.noreply.github.com> Date: Thu, 7 Dec 2023 16:12:48 +0000 Subject: [PATCH 11/64] Substituted the letter 'z' with 'x' in pre-declaration --- slither/detectors/variables/predeclaration_usage_local.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/variables/predeclaration_usage_local.py b/slither/detectors/variables/predeclaration_usage_local.py index b4d75e51a..9816dd6e2 100644 --- a/slither/detectors/variables/predeclaration_usage_local.py +++ b/slither/detectors/variables/predeclaration_usage_local.py @@ -36,7 +36,7 @@ class PredeclarationUsageLocal(AbstractDetector): ```solidity contract C { function f(uint z) public returns (uint) { - uint y = x + 9 + z; // 'z' is used pre-declaration + uint y = x + 9 + z; // 'x' is used pre-declaration uint x = 7; if (z % 2 == 0) { From a0365982add762e2bb4abb80cdea9b272bcddd61 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Tue, 2 Jan 2024 09:20:59 -0500 Subject: [PATCH 12/64] updated mutator --- slither/tools/mutator/__main__.py | 81 +++++++++++++++---- slither/tools/mutator/mutators/MIA.py | 73 +++++++++++------ slither/tools/mutator/mutators/MVIE.py | 45 ++++++----- slither/tools/mutator/mutators/MVIV.py | 45 ++++++----- .../mutator/mutators/abstract_mutator.py | 19 +++-- slither/tools/mutator/utils/command_line.py | 2 - slither/tools/mutator/utils/file_handling.py | 77 ++++++++++++++++++ .../tools/mutator/utils/generic_patching.py | 30 ++++--- .../tools/mutator/utils/replace_conditions.py | 43 ++++++++++ .../mutator/utils/testing_generated_mutant.py | 31 +++++++ 10 files changed, 349 insertions(+), 97 deletions(-) create mode 100644 slither/tools/mutator/utils/file_handling.py create mode 100644 slither/tools/mutator/utils/replace_conditions.py create mode 100644 slither/tools/mutator/utils/testing_generated_mutant.py diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 84286ce66..fde87e5e2 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -2,7 +2,8 @@ import argparse import inspect import logging import sys -from typing import Type, List, Any +from typing import Type, List, Any, Dict, Tuple +import os from crytic_compile import cryticparser @@ -10,9 +11,10 @@ from slither import Slither from slither.tools.mutator.mutators import all_mutators from .mutators.abstract_mutator import AbstractMutator from .utils.command_line import output_mutators +from .utils.file_handling import transfer_and_delete, backup_source_file, get_sol_file_list logging.basicConfig() -logger = logging.getLogger("Slither") +logger = logging.getLogger("Slither-Mutate") logger.setLevel(logging.INFO) @@ -22,7 +24,6 @@ logger.setLevel(logging.INFO) ################################################################################### ################################################################################### - def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Experimental smart contract mutator. Based on https://arxiv.org/abs/2006.11597", @@ -39,6 +40,22 @@ def parse_args() -> argparse.Namespace: default=False, ) + parser.add_argument( + "--test-cmd", + help="Command line needed to run the tests for your project" + ) + + parser.add_argument( + "--test-dir", + help="Directory of tests" + ) + + # parameter to ignore the interfaces, libraries + parser.add_argument( + "--ignore-dirs", + help="Directories to ignore" + ) + # Initiate all the crytic config cli options cryticparser.init(parser) @@ -73,16 +90,52 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def main() -> None: - args = parse_args() - - print(args.codebase) - sl = Slither(args.codebase, **vars(args)) - - for compilation_unit in sl.compilation_units: - for M in _get_mutators(): - m = M(compilation_unit) - m.mutate() - - + # print(os.path.isdir(args.codebase)) # provided file/folder + + # arguments + test_command: str = args.test_cmd + test_directory: str = args.test_dir + paths_to_ignore: List[str] = args.ignore_dirs + + # get all the contracts as a list from given codebase + sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore) + + print("Starting Mutation Campaign in", args.codebase, "\n") + for filename in sol_file_list: + # slither object + sl = Slither(filename, **vars(args)) + + # folder where backup files and valid mutants created + output_folder = os.getcwd() + "/mutation_campaign" + + # create a backup files + files_dict = backup_source_file(sl.source_code, output_folder) + + # total count of valid mutants + total_count = 0 + + # mutation + try: + for compilation_unit_of_main_file in sl.compilation_units: + # compilation_unit_of_main_file = sl.compilation_units[-1] + # for i in compilation_unit_of_main_file.contracts: + # print(i.name) + for M in _get_mutators(): + m = M(compilation_unit_of_main_file) + count = m.mutate(test_command, test_directory) + if count != None: + total_count = total_count + count + except Exception as e: + logger.error(e) + + # transfer and delete the backup files + transfer_and_delete(files_dict) + + # output + print(f"Done mutating, '{filename}'") + print(f"Valid mutant count: '{total_count}'\n") + + print("Finished Mutation Campaign in", args.codebase, "\n") # endregion + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 405888f8b..370f419c1 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -1,39 +1,60 @@ -from typing import Dict - +from typing import Dict, Tuple from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass - +from slither.tools.mutator.utils.testing_generated_mutant import compile_generated_mutant, run_test_suite +from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file_specific_line +from slither.tools.mutator.utils.file_handling import create_mutant_file class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" HELP = '"if" construct around statement' FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing + VALID_MUTANTS_COUNT = 1 - def _mutate(self) -> Dict: + def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: result: Dict = {} - + for contract in self.slither.contracts: - - for function in contract.functions_declared + list(contract.modifiers_declared): - - for node in function.nodes: - if node.type == NodeType.IF: - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] - - # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] - - # Replace the expression with true - new_str = "true" - - create_patch(result, in_file, start, stop, old_str, new_str) - - return result + if not contract.is_library: + if not contract.is_interface: + for function in contract.functions_declared + list(contract.modifiers_declared): + for node in function.nodes: + if node.contains_if(): + # print(node.expression) + # Retrieve the file + in_file = contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = contract.compilation_unit.core.source_code[in_file] + + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + # old_str = in_file_str[start:stop] + old_str = str(node.expression) + line_no = node.source_mapping.lines + print(line_no) + # Replace the expression with true + new_str = "true" + + replace_string_in_source_file_specific_line(in_file, old_str, new_str, line_no[0]) + + # compile and run tests + if compile_generated_mutant(in_file): + if run_test_suite(test_cmd, test_dir): + # print(True) + # generate the mutant and patch + create_mutant_file(in_file, self.VALID_MUTANTS_COUNT, self.NAME) + create_patch(result, in_file, start, stop, old_str, new_str) + + + + return (result, self.VALID_MUTANTS_COUNT) + + + + + + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index a16a8252e..9dccc9f13 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -1,36 +1,41 @@ -from typing import Dict +from typing import Dict, Tuple from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass from slither.tools.mutator.utils.generic_patching import remove_assignement - +from slither.tools.mutator.utils.file_handling import create_mutant_file class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" HELP = "variable initialization using an expression" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing + VALID_MUTANTS_COUNT = 1 - def _mutate(self) -> Dict: + def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: result: Dict = {} variable: Variable for contract in self.slither.contracts: - - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue - - if not isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) - - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and not isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) - - return result + if not contract.is_library: + if not contract.is_interface: + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue + + if not isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and not isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + + return (result, self.VALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index d4a7c5486..9e7b143ae 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -1,37 +1,42 @@ -from typing import Dict +from typing import Dict, Tuple from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass from slither.tools.mutator.utils.generic_patching import remove_assignement - +from slither.tools.mutator.utils.file_handling import create_mutant_file class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" HELP = "variable initialization using a value" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing + VALID_MUTANTS_COUNT = 1 - def _mutate(self) -> Dict: + def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: result: Dict = {} variable: Variable for contract in self.slither.contracts: - - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue - - if isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) - - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) - - return result + if not contract.is_library: + if not contract.is_interface: + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue + + if isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + return (result, self.VALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index 169d8725e..ab295e295 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -4,9 +4,10 @@ from enum import Enum from typing import Optional, Dict from slither.core.compilation_unit import SlitherCompilationUnit +from slither.tools.doctor.utils import snip_section from slither.formatters.utils.patches import apply_patch, create_diff -logger = logging.getLogger("Slither") +logger = logging.getLogger("Slither-Mutate") class IncorrectMutatorInitialization(Exception): @@ -68,13 +69,14 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- ) @abc.abstractmethod - def _mutate(self) -> Dict: + def _mutate(self, test_cmd: str, test_dir: str) -> Dict: """TODO Documentation""" return {} - def mutate(self) -> None: - all_patches = self._mutate() - + def mutate(self, testing_command: str, testing_directory: str) -> int: + # call _mutate function from different mutators + (all_patches, valid_mutant_count) = self._mutate(testing_command, testing_directory) + if "patches" not in all_patches: logger.debug(f"No patches found by {self.NAME}") return @@ -93,4 +95,11 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) if not diff: logger.info(f"Impossible to generate patch; empty {patches}") + # print the differences print(diff) + + return valid_mutant_count + + + + \ No newline at end of file diff --git a/slither/tools/mutator/utils/command_line.py b/slither/tools/mutator/utils/command_line.py index feb479c5c..80d610a69 100644 --- a/slither/tools/mutator/utils/command_line.py +++ b/slither/tools/mutator/utils/command_line.py @@ -1,9 +1,7 @@ from typing import List, Type - from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.utils.myprettytable import MyPrettyTable - def output_mutators(mutators_classes: List[Type[AbstractMutator]]) -> None: mutators_list = [] for detector in mutators_classes: diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py new file mode 100644 index 000000000..800232a5a --- /dev/null +++ b/slither/tools/mutator/utils/file_handling.py @@ -0,0 +1,77 @@ +import os +from typing import Dict, Tuple, List +import logging + +logger = logging.getLogger("Slither-Mutate") + +# function to backup the source file +def backup_source_file(source_code: Dict, output_folder: str) -> Dict: + duplicated_files = {} + os.makedirs(output_folder, exist_ok=True) + + for file_path, content in source_code.items(): + directory, filename = os.path.split(file_path) + new_filename = f"{output_folder}/backup_{filename}" + new_file_path = os.path.join(directory, new_filename) + + with open(new_file_path, 'w') as new_file: + new_file.write(content) + duplicated_files[file_path] = new_file_path + + return duplicated_files + +# function to transfer the original content to the sol file after campaign +def transfer_and_delete(files_dict: Dict) -> None: + try: + for item, value in files_dict.items(): + with open(value, 'r') as duplicated_file: + content = duplicated_file.read() + + with open(item, 'w') as original_file: + original_file.write(content) + + os.remove(value) + except Exception as e: + logger.error(f"Error transferring content: {e}") + +#function to create new mutant file +def create_mutant_file(file: str, count: int, rule: str) -> None: + try: + directory, filename = os.path.split(file) + # Read content from the duplicated file + with open(file, 'r') as source_file: + content = source_file.read() + + # Write content to the original file + mutant_name = filename.split('.')[0] + with open("mutation_campaign/" + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: + mutant_file.write(content) + + except Exception as e: + logger.error(f"Error creating mutant: {e}") + +# function to get the contracts list +def get_sol_file_list(codebase: str, ignore_paths: List[str]) -> List[str]: + sol_file_list = [] + + # if input is contract file + if os.path.isfile(codebase): + return [codebase] + + # if input is folder + elif os.path.isdir(codebase): + directory = os.path.abspath(codebase) + for file in os.listdir(directory): + filename = os.path.join(directory, file) + if os.path.isfile(filename): + sol_file_list.append(filename) + elif os.path.isdir(filename): + directory_name, dirname = os.path.split(filename) + if dirname in ignore_paths: + continue + for i in get_sol_file_list(filename, ignore_paths): + sol_file_list.append(i) + + return sol_file_list +# to_do: create a function to delete the commands from the sol file +# def remove_comments(self) -> None: \ No newline at end of file diff --git a/slither/tools/mutator/utils/generic_patching.py b/slither/tools/mutator/utils/generic_patching.py index d773ea784..03ccadec7 100644 --- a/slither/tools/mutator/utils/generic_patching.py +++ b/slither/tools/mutator/utils/generic_patching.py @@ -1,11 +1,14 @@ from typing import Dict +import os from slither.core.declarations import Contract from slither.core.variables.variable import Variable from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.testing_generated_mutant import compile_generated_mutant, run_test_suite +from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file +from slither.tools.mutator.utils.file_handling import create_mutant_file - -def remove_assignement(variable: Variable, contract: Contract, result: Dict): +def remove_assignement(variable: Variable, contract: Contract, result: Dict, test_cmd: str, test_dir: str) -> bool: """ Remove the variable's initial assignement @@ -25,12 +28,19 @@ def remove_assignement(variable: Variable, contract: Contract, result: Dict): old_str = in_file_str[start:stop] new_str = old_str[: old_str.find("=")] + + replace_string_in_source_file(in_file, in_file_str[variable.source_mapping.start + old_str.find("="):variable.source_mapping.end], '') - create_patch( - result, - in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - ) + # compile and run tests before the mutant generated before patching + if compile_generated_mutant(in_file): + if run_test_suite(test_cmd, test_dir): + # create_mutant_file(in_file, ) + create_patch( + result, + in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + ) + return True \ No newline at end of file diff --git a/slither/tools/mutator/utils/replace_conditions.py b/slither/tools/mutator/utils/replace_conditions.py new file mode 100644 index 000000000..82d6c11c9 --- /dev/null +++ b/slither/tools/mutator/utils/replace_conditions.py @@ -0,0 +1,43 @@ +import logging + +logger = logging.getLogger("Slither-Mutate") + +# function to replace the string +def replace_string_in_source_file(file_path: str, old_string: str, new_string: str) -> None: + try: + # Read the content of the Solidity file + with open(file_path, 'r') as file: + content = file.read() + + # Perform the string replacement + modified_content = content.replace(old_string, new_string) + + # Write the modified content back to the file + with open(file_path, 'w') as file: + file.write(modified_content) + + logger.info(f"String '{old_string}' replaced with '{new_string}' in '{file_path}'.") + except Exception as e: + logger.error(f"Error replacing string: {e}") + +# function to replace the string in a specific line +def replace_string_in_source_file_specific_line(file_path: str, old_string: str, new_string: str, line_number : int) -> None: + try: + # Read the content of the Solidity file + with open(file_path, 'r') as file: + lines = file.readlines() + + if 1 <= line_number <= len(lines): + # Replace the old string with the new string on the specified line + lines[line_number - 1] = lines[line_number - 1].replace(old_string, new_string) + + # Write the modified content back to the file + with open(file_path, 'w') as file: + file.writelines(lines) + + logger.info(f"String '{old_string}' replaced with '{new_string}' in '{file_path}'.' at '{line_number}") + else: + logger.error(f'Error: Line number {line_number} is out of range') + + except Exception as e: + logger.erro(f'Error: {e}') \ No newline at end of file diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py new file mode 100644 index 000000000..1c7de9acf --- /dev/null +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -0,0 +1,31 @@ +import crytic_compile +import subprocess +import os +import logging + +logger = logging.getLogger("Slither-Mutate") + +# function to compile the generated mutant +def compile_generated_mutant(file_path: str) -> bool: + try: + crytic_compile.CryticCompile(file_path) + return True + except Exception as e: # pylint: disable=broad-except + logger.error("Error Crytic Compile", e) + +# function to run the tests +def run_test_suite(cmd: str, dir: str) -> bool: + try: + # Change to the foundry folder + # os.chdir(dir) + + result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + if not result.stderr: + return True + except subprocess.CalledProcessError as e: + logger.error(f"Error executing 'forge test': {e}") + return False + except Exception as e: + logger.error(f"An unexpected error occurred: {e}") + return False \ No newline at end of file From 37c23e11ce63f229593a500e7a1d8512d00cce43 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Wed, 3 Jan 2024 11:35:08 -0500 Subject: [PATCH 13/64] Updated replace string logic --- slither/tools/mutator/__main__.py | 31 +++++--- slither/tools/mutator/mutators/MIA.py | 72 ++++++++++--------- slither/tools/mutator/mutators/MVIE.py | 44 ++++++------ slither/tools/mutator/mutators/MVIV.py | 44 ++++++------ .../mutator/mutators/abstract_mutator.py | 8 +-- .../tools/mutator/mutators/all_mutators.py | 4 +- slither/tools/mutator/utils/file_handling.py | 10 ++- .../tools/mutator/utils/replace_conditions.py | 9 ++- .../mutator/utils/testing_generated_mutant.py | 7 +- 9 files changed, 131 insertions(+), 98 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index fde87e5e2..9cb1a9f8d 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -40,11 +40,13 @@ def parse_args() -> argparse.Namespace: default=False, ) + # argument to add the test command parser.add_argument( "--test-cmd", help="Command line needed to run the tests for your project" ) + # argument to add the test directory - containing all the tests parser.add_argument( "--test-dir", help="Directory of tests" @@ -96,13 +98,14 @@ def main() -> None: # arguments test_command: str = args.test_cmd test_directory: str = args.test_dir - paths_to_ignore: List[str] = args.ignore_dirs + paths_to_ignore: List[str] | None = args.ignore_dirs # get all the contracts as a list from given codebase sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore) print("Starting Mutation Campaign in", args.codebase, "\n") for filename in sol_file_list: + contract_name = os.path.split(filename)[1].split('.sol')[0] # slither object sl = Slither(filename, **vars(args)) @@ -112,9 +115,12 @@ def main() -> None: # create a backup files files_dict = backup_source_file(sl.source_code, output_folder) - # total count of valid mutants + # total count of mutants total_count = 0 - + + # count of valid mutants + v_count = 0 + # mutation try: for compilation_unit_of_main_file in sl.compilation_units: @@ -123,19 +129,24 @@ def main() -> None: # print(i.name) for M in _get_mutators(): m = M(compilation_unit_of_main_file) - count = m.mutate(test_command, test_directory) - if count != None: - total_count = total_count + count + v_count, i_count = m.mutate(test_command, test_directory, contract_name) + if v_count != None and i_count != None: + total_count = total_count + v_count + i_count except Exception as e: logger.error(e) + except KeyboardInterrupt: + # transfer and delete the backup files if interrupted + logger.error("\nExecution interrupted by user (Ctrl + C). Cleaning up...") + transfer_and_delete(files_dict) + # transfer and delete the backup files transfer_and_delete(files_dict) - - # output - print(f"Done mutating, '{filename}'") - print(f"Valid mutant count: '{total_count}'\n") + + # output + print(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n") + print("Finished Mutation Campaign in", args.codebase, "\n") # endregion \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 370f419c1..b1c55d184 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -11,47 +11,53 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods HELP = '"if" construct around statement' FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 1 + VALID_MUTANTS_COUNT = 0 + INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: + def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: result: Dict = {} for contract in self.slither.contracts: - if not contract.is_library: - if not contract.is_interface: - for function in contract.functions_declared + list(contract.modifiers_declared): - for node in function.nodes: - if node.contains_if(): - # print(node.expression) - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] + # if not contract.is_library: + # if not contract.is_interface: + if contract_name == str(contract.name): + for function in contract.functions_declared + list(contract.modifiers_declared): + for node in function.nodes: + if node.contains_if(): + # print(node.expression) + # Retrieve the file + in_file = contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = contract.compilation_unit.core.source_code[in_file] - # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length - # old_str = in_file_str[start:stop] - old_str = str(node.expression) - line_no = node.source_mapping.lines - print(line_no) - # Replace the expression with true - new_str = "true" - - replace_string_in_source_file_specific_line(in_file, old_str, new_str, line_no[0]) - - # compile and run tests - if compile_generated_mutant(in_file): - if run_test_suite(test_cmd, test_dir): - # print(True) - # generate the mutant and patch - create_mutant_file(in_file, self.VALID_MUTANTS_COUNT, self.NAME) - create_patch(result, in_file, start, stop, old_str, new_str) - + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + # old_str = in_file_str[start:stop] + old_str = str(node.expression) + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = "true" + print(line_no[0]) + replace_string_in_source_file_specific_line(in_file, old_str, new_str, line_no[0]) + + # compile and run tests + if compile_generated_mutant(in_file): + if run_test_suite(test_cmd, test_dir): + # generate the mutant and patch + create_mutant_file(in_file, self.VALID_MUTANTS_COUNT, self.NAME) + create_patch(result, in_file, start, stop, old_str, new_str) + self.VALID_MUTANTS_COUNT = self.VALID_MUTANTS_COUNT + 1 + else: + self.INVALID_MUTANTS_COUNT = self.INVALID_MUTANTS_COUNT + 1 + else: + self.INVALID_MUTANTS_COUNT = self.INVALID_MUTANTS_COUNT + 1 + print(self.INVALID_MUTANTS_COUNT) + - return (result, self.VALID_MUTANTS_COUNT) + return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 9dccc9f13..1c99b24ee 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -11,31 +11,33 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods HELP = "variable initialization using an expression" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 1 + VALID_MUTANTS_COUNT = 0 + INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: + def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: result: Dict = {} variable: Variable for contract in self.slither.contracts: - if not contract.is_library: - if not contract.is_interface: - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue + # if not contract.is_library: + # if not contract.is_interface: + if contract_name == str(contract.name): + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue - if not isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and not isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - + if not isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and not isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + - return (result, self.VALID_MUTANTS_COUNT) + return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index 9e7b143ae..bb1c4cabe 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -11,32 +11,34 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods HELP = "variable initialization using a value" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 1 + VALID_MUTANTS_COUNT = 0 + INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: + def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: result: Dict = {} variable: Variable for contract in self.slither.contracts: - if not contract.is_library: - if not contract.is_interface: - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue + # if not contract.is_library: + # if not contract.is_interface: + if contract_name == str(contract.name): + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue - if isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - + if isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - - return (result, self.VALID_MUTANTS_COUNT) + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index ab295e295..a79f45906 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -1,7 +1,7 @@ import abc import logging from enum import Enum -from typing import Optional, Dict +from typing import Optional, Dict, Tuple from slither.core.compilation_unit import SlitherCompilationUnit from slither.tools.doctor.utils import snip_section @@ -73,9 +73,9 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- """TODO Documentation""" return {} - def mutate(self, testing_command: str, testing_directory: str) -> int: + def mutate(self, testing_command: str, testing_directory: str, contract_name: str) -> Tuple[(int, int)]: # call _mutate function from different mutators - (all_patches, valid_mutant_count) = self._mutate(testing_command, testing_directory) + (all_patches, valid_mutant_count, invalid_mutant_count) = self._mutate(testing_command, testing_directory, contract_name) if "patches" not in all_patches: logger.debug(f"No patches found by {self.NAME}") @@ -98,7 +98,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # print the differences print(diff) - return valid_mutant_count + return (valid_mutant_count, invalid_mutant_count) diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 5508fb68e..5a9465c86 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -1,4 +1,4 @@ # pylint: disable=unused-import -from slither.tools.mutator.mutators.MVIV import MVIV -from slither.tools.mutator.mutators.MVIE import MVIE +# from slither.tools.mutator.mutators.MVIV import MVIV +# from slither.tools.mutator.mutators.MVIE import MVIE from slither.tools.mutator.mutators.MIA import MIA diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index 800232a5a..c041f76d6 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -36,6 +36,7 @@ def transfer_and_delete(files_dict: Dict) -> None: #function to create new mutant file def create_mutant_file(file: str, count: int, rule: str) -> None: + try: directory, filename = os.path.split(file) # Read content from the duplicated file @@ -44,16 +45,19 @@ def create_mutant_file(file: str, count: int, rule: str) -> None: # Write content to the original file mutant_name = filename.split('.')[0] - with open("mutation_campaign/" + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: + # create folder for each contract + os.makedirs("mutation_campaign/" + mutant_name, exist_ok=True) + with open("mutation_campaign/" + mutant_name + '/' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: mutant_file.write(content) except Exception as e: logger.error(f"Error creating mutant: {e}") # function to get the contracts list -def get_sol_file_list(codebase: str, ignore_paths: List[str]) -> List[str]: +def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str]: sol_file_list = [] - + if ignore_paths == None: + ignore_paths = [] # if input is contract file if os.path.isfile(codebase): return [codebase] diff --git a/slither/tools/mutator/utils/replace_conditions.py b/slither/tools/mutator/utils/replace_conditions.py index 82d6c11c9..4e3f91454 100644 --- a/slither/tools/mutator/utils/replace_conditions.py +++ b/slither/tools/mutator/utils/replace_conditions.py @@ -1,4 +1,5 @@ import logging +import re logger = logging.getLogger("Slither-Mutate") @@ -8,7 +9,7 @@ def replace_string_in_source_file(file_path: str, old_string: str, new_string: s # Read the content of the Solidity file with open(file_path, 'r') as file: content = file.read() - + # Perform the string replacement modified_content = content.replace(old_string, new_string) @@ -28,8 +29,12 @@ def replace_string_in_source_file_specific_line(file_path: str, old_string: str, lines = file.readlines() if 1 <= line_number <= len(lines): + # remove the spaces in the string + line = lines[line_number - 1].replace(" ", "") + old_string = old_string.replace(" ", "") + # Replace the old string with the new string on the specified line - lines[line_number - 1] = lines[line_number - 1].replace(old_string, new_string) + lines[line_number - 1] = line.replace(old_string.strip(), new_string) # Write the modified content back to the file with open(file_path, 'w') as file: diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 1c7de9acf..61b9db214 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -20,11 +20,14 @@ def run_test_suite(cmd: str, dir: str) -> bool: # os.chdir(dir) result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - + # result = subprocess.run(cmd.split(' '), check=True) + print(result.stdout) if not result.stderr: return True except subprocess.CalledProcessError as e: - logger.error(f"Error executing 'forge test': {e}") + print(e.output) + logger.error(f"Error executing '{cmd}': {e}") + return False except Exception as e: logger.error(f"An unexpected error occurred: {e}") From 36eda1b3cb8599033097e613750eb7db154c5b55 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Fri, 5 Jan 2024 19:31:25 -0500 Subject: [PATCH 14/64] Added new mutant generators --- slither/tools/mutator/__main__.py | 44 ++++++--- slither/tools/mutator/mutators/LOR.py | 47 ++++++++++ slither/tools/mutator/mutators/MIA.py | 65 ++++--------- slither/tools/mutator/mutators/MVIE.py | 48 ++++------ slither/tools/mutator/mutators/MVIV.py | 41 ++++---- slither/tools/mutator/mutators/ROR.py | 53 +++++++++++ slither/tools/mutator/mutators/SBR.py | 94 +++++++++++++++++++ slither/tools/mutator/mutators/UOI.py | 56 +++++++++++ .../mutator/mutators/abstract_mutator.py | 46 ++++++--- .../tools/mutator/mutators/all_mutators.py | 7 +- slither/tools/mutator/utils/file_handling.py | 34 ++++++- .../tools/mutator/utils/generic_patching.py | 28 +++--- .../mutator/utils/testing_generated_mutant.py | 58 +++++++++++- 13 files changed, 467 insertions(+), 154 deletions(-) create mode 100644 slither/tools/mutator/mutators/LOR.py create mode 100644 slither/tools/mutator/mutators/ROR.py create mode 100644 slither/tools/mutator/mutators/SBR.py create mode 100644 slither/tools/mutator/mutators/UOI.py diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 9cb1a9f8d..201b39acd 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -4,6 +4,7 @@ import logging import sys from typing import Type, List, Any, Dict, Tuple import os +import shutil from crytic_compile import cryticparser @@ -12,12 +13,12 @@ from slither.tools.mutator.mutators import all_mutators from .mutators.abstract_mutator import AbstractMutator from .utils.command_line import output_mutators from .utils.file_handling import transfer_and_delete, backup_source_file, get_sol_file_list +from slither.utils.colors import yellow, magenta logging.basicConfig() logger = logging.getLogger("Slither-Mutate") logger.setLevel(logging.INFO) - ################################################################################### ################################################################################### # region Cli Arguments @@ -52,12 +53,17 @@ def parse_args() -> argparse.Namespace: help="Directory of tests" ) - # parameter to ignore the interfaces, libraries + # argument to ignore the interfaces, libraries parser.add_argument( "--ignore-dirs", help="Directories to ignore" ) + # to_do: add time out argument + parser.add_argument( + "--timeout", + help="Set timeout for test command" + ) # Initiate all the crytic config cli options cryticparser.init(parser) @@ -90,7 +96,6 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods ################################################################################### ################################################################################### - def main() -> None: args = parse_args() # print(os.path.isdir(args.codebase)) # provided file/folder @@ -98,19 +103,29 @@ def main() -> None: # arguments test_command: str = args.test_cmd test_directory: str = args.test_dir - paths_to_ignore: List[str] | None = args.ignore_dirs + paths_to_ignore: str | None = args.ignore_dirs + timeout: int = args.timeout + + print(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) + + if paths_to_ignore: + paths_to_ignore_list = paths_to_ignore.strip('][').split(',') + print(magenta(f"Ignored paths - {', '.join(paths_to_ignore_list)} \n")) + else: + paths_to_ignore_list = [] # get all the contracts as a list from given codebase - sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore) + sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore_list) + + # folder where backup files and valid mutants created + output_folder = os.getcwd() + "/mutation_campaign" + if os.path.exists(output_folder): + shutil.rmtree(output_folder) - print("Starting Mutation Campaign in", args.codebase, "\n") for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] # slither object sl = Slither(filename, **vars(args)) - - # folder where backup files and valid mutants created - output_folder = os.getcwd() + "/mutation_campaign" # create a backup files files_dict = backup_source_file(sl.source_code, output_folder) @@ -129,9 +144,9 @@ def main() -> None: # print(i.name) for M in _get_mutators(): m = M(compilation_unit_of_main_file) - v_count, i_count = m.mutate(test_command, test_directory, contract_name) - if v_count != None and i_count != None: - total_count = total_count + v_count + i_count + count_valid, count_invalid = m.mutate(test_command, test_directory, contract_name) + v_count += count_valid + total_count += count_valid + count_invalid except Exception as e: logger.error(e) @@ -143,10 +158,9 @@ def main() -> None: # transfer and delete the backup files transfer_and_delete(files_dict) - # output - print(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n") + print(yellow(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n")) - print("Finished Mutation Campaign in", args.codebase, "\n") + print(magenta(f"Finished Mutation Campaign in '{args.codebase}' \n")) # endregion \ No newline at end of file diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py new file mode 100644 index 000000000..382a08aee --- /dev/null +++ b/slither/tools/mutator/mutators/LOR.py @@ -0,0 +1,47 @@ +from typing import Dict +from slither.slithir.operations import Binary, BinaryType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass + +logical_operators = [ + BinaryType.OROR, + BinaryType.ANDAND, +] + +class LOR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "LOR" + HELP = "Logical operator replacement" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + + result: Dict = {} + + contract = self.contract + + # Retrieve the file + in_file = contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = contract.compilation_unit.core.source_code[in_file] + for function in contract.functions_and_modifiers_declared: + + for node in function.nodes: + for ir in node.irs: + if isinstance(ir, Binary) and ir.type in logical_operators: + alternative_ops = logical_operators[:] + alternative_ops.remove(ir.type) + + for op in alternative_ops: + + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + # new_str = f"{ir.variable_left} {op.value} {ir.variable_right}" + new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" + + create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index b1c55d184..d76369d4d 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -1,63 +1,38 @@ -from typing import Dict, Tuple +from typing import Dict from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass -from slither.tools.mutator.utils.testing_generated_mutant import compile_generated_mutant, run_test_suite -from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file_specific_line -from slither.tools.mutator.utils.file_handling import create_mutant_file class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" HELP = '"if" construct around statement' FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 0 - INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: + def _mutate(self) -> Dict: result: Dict = {} + # Retrieve the file + in_file = self.contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = self.contract.compilation_unit.core.source_code[in_file] - for contract in self.slither.contracts: - # if not contract.is_library: - # if not contract.is_interface: - if contract_name == str(contract.name): - for function in contract.functions_declared + list(contract.modifiers_declared): - for node in function.nodes: - if node.contains_if(): - # print(node.expression) - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] + for function in self.contract.functions_declared + list(self.contract.modifiers_declared): + for node in function.nodes: + if node.type == NodeType.IF: + + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + line_no = node.source_mapping.lines - # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length - # old_str = in_file_str[start:stop] - old_str = str(node.expression) - line_no = node.source_mapping.lines - # Replace the expression with true - new_str = "true" - print(line_no[0]) - replace_string_in_source_file_specific_line(in_file, old_str, new_str, line_no[0]) - - # compile and run tests - if compile_generated_mutant(in_file): - if run_test_suite(test_cmd, test_dir): - # generate the mutant and patch - create_mutant_file(in_file, self.VALID_MUTANTS_COUNT, self.NAME) - create_patch(result, in_file, start, stop, old_str, new_str) - self.VALID_MUTANTS_COUNT = self.VALID_MUTANTS_COUNT + 1 - else: - self.INVALID_MUTANTS_COUNT = self.INVALID_MUTANTS_COUNT + 1 - else: - self.INVALID_MUTANTS_COUNT = self.INVALID_MUTANTS_COUNT + 1 - print(self.INVALID_MUTANTS_COUNT) + # Replace the expression with true and false + for value in ["true", "false"]: + new_str = value + create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) - - - return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) + return result diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 1c99b24ee..15b2a20c3 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -1,43 +1,35 @@ -from typing import Dict, Tuple +from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass from slither.tools.mutator.utils.generic_patching import remove_assignement -from slither.tools.mutator.utils.file_handling import create_mutant_file class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" HELP = "variable initialization using an expression" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 0 - INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: + def _mutate(self) -> Dict: result: Dict = {} variable: Variable - for contract in self.slither.contracts: - # if not contract.is_library: - # if not contract.is_interface: - if contract_name == str(contract.name): - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue - - if not isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and not isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - - - return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) + contract = self.contract + + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue + + if not isinstance(variable.expression, Literal): + remove_assignement(variable, contract, result) + + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and not isinstance(variable.expression, Literal): + remove_assignement(variable, contract, result) + + return result diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index bb1c4cabe..5e7c0a6e1 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -4,41 +4,32 @@ from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass from slither.tools.mutator.utils.generic_patching import remove_assignement -from slither.tools.mutator.utils.file_handling import create_mutant_file class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" HELP = "variable initialization using a value" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 0 - INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: + def _mutate(self) -> Dict: result: Dict = {} variable: Variable + contract = self.contract + + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue - for contract in self.slither.contracts: - # if not contract.is_library: - # if not contract.is_interface: - if contract_name == str(contract.name): - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue + if isinstance(variable.expression, Literal): + remove_assignement(variable, contract, result) - if isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and isinstance(variable.expression, Literal): + remove_assignement(variable, contract, result) - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - - return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) + return result diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py new file mode 100644 index 000000000..9a8942e19 --- /dev/null +++ b/slither/tools/mutator/mutators/ROR.py @@ -0,0 +1,53 @@ +from typing import Dict +from collections import defaultdict +from slither.slithir.operations import Binary, BinaryType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass + + +relational_operators = [ + BinaryType.LESS, + BinaryType.GREATER, + BinaryType.LESS_EQUAL, + BinaryType.GREATER_EQUAL, + BinaryType.EQUAL, + BinaryType.NOT_EQUAL, +] + + +class ROR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "ROR" + HELP = "Relational operator replacement" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + + result: Dict = {} + # result["patches"] = defaultdict(list) + contract = self.contract + + for function in contract.functions_and_modifiers_declared: + for node in function.nodes: + for ir in node.irs: + # Retrieve the file + in_file = self.contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = self.contract.compilation_unit.core.source_code[in_file] + + if isinstance(ir, Binary) and ir.type in relational_operators: + alternative_ops = relational_operators[:] + alternative_ops.remove(ir.type) + + for op in alternative_ops: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" + + create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py new file mode 100644 index 000000000..ac35d9540 --- /dev/null +++ b/slither/tools/mutator/mutators/SBR.py @@ -0,0 +1,94 @@ +from typing import Dict +from slither.core.cfg.node import NodeType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +import re + +solidity_rules = [ + "abi\.encode\( ==> abi.encodePacked(", + "abi\.encodePacked\( ==> abi.encode(", + "\.call([({]) ==> .delegatecall\\1", + "\.call([({]) ==> .staticcall\\1", + "\.delegatecall([({]) ==> .call\\1", + "\.delegatecall([({]) ==> .staticcall\\1", + "\.staticcall([({]) ==> .delegatecall\\1", + "\.staticcall([({]) ==> .call\\1", + "^now$ ==> 0", + "block.timestamp ==> 0", + "msg.value ==> 0", + "msg.value ==> 1", + "(\s)(wei|gwei) ==> \\1ether", + "(\s)(ether|gwei) ==> \\1wei", + "(\s)(wei|ether) ==> \\1gwei", + "(\s)(minutes|days|hours|weeks) ==> \\1seconds", + "(\s)(seconds|days|hours|weeks) ==> \\1minutes", + "(\s)(seconds|minutes|hours|weeks) ==> \\1days", + "(\s)(seconds|minutes|days|weeks) ==> \\1hours", + "(\s)(seconds|minutes|days|hours) ==> \\1weeks", + "(\s)(memory) ==> \\1storage", + "(\s)(storage) ==> \\1memory", + "(\s)(constant) ==> \\1immutable", + "addmod ==> mulmod", + "mulmod ==> addmod", + "msg.sender ==> tx.origin", + "tx.origin ==> msg.sender", + "([^u])fixed ==> \\1ufixed", + "ufixed ==> fixed", + "(u?)int16 ==> \\1int8", + "(u?)int32 ==> \\1int16", + "(u?)int64 ==> \\1int32", + "(u?)int128 ==> \\1int64", + "(u?)int256 ==> \\1int128" +] + + +class SBR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "SBR" + HELP = 'Solidity Based Replacements' + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + + result: Dict = {} + contract = self.contract + # Retrieve the file + in_file = contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = contract.compilation_unit.core.source_code[in_file] + + for function in contract.functions_and_modifiers_declared: + for node in function.nodes: + if node.type != NodeType.ENTRYPOINT: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + line_no = node.source_mapping.lines + for value in solidity_rules: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + + for variable in contract.state_variables_declared: + node = variable.node_initialization + if node: + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + line_no = node.source_mapping.lines + for value in solidity_rules: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + return result + + + + + + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/UOI.py b/slither/tools/mutator/mutators/UOI.py new file mode 100644 index 000000000..6d5862e76 --- /dev/null +++ b/slither/tools/mutator/mutators/UOI.py @@ -0,0 +1,56 @@ +from typing import Dict +import re +from slither.core.expressions.unary_operation import UnaryOperationType +from slither.slithir.variables import Constant +from slither.core.variables.local_variable import LocalVariable +from slither.core.expressions.expression import Expression +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.core.cfg.node import NodeType + + +unary_operators = [ + UnaryOperationType.PLUSPLUS_PRE, + UnaryOperationType.MINUSMINUS_PRE, + UnaryOperationType.PLUSPLUS_POST, + UnaryOperationType.MINUSMINUS_POST, + UnaryOperationType.MINUS_PRE, +] + + +class UOI(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "UOI" + HELP = "Unary operator insertion" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + + result: Dict = {} + + contract = self.contract + + # Retrieve the file + in_file = contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = contract.compilation_unit.core.source_code[in_file] + + for function in contract.functions_and_modifiers_declared: + for node in function.nodes: + if (node.type == NodeType.EXPRESSION): + for op in unary_operators: + if str(op) in str(node.expression): + for i in node.variables_written: + print(i) + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + # print(old_str) + # Replace the expression with true + # new_str = old_str.replace(str(operand), f"{str(op)}{operand}") + # new_str = re.sub(r'(\w+)\+\+', r'++\1', text) + # print(new_str) + # create_patch(result, in_file, start, stop, old_str, new_str) + print(result) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index a79f45906..e58b705a1 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -1,12 +1,12 @@ import abc import logging from enum import Enum -from typing import Optional, Dict, Tuple +from typing import Optional, Dict, Tuple, List from slither.core.compilation_unit import SlitherCompilationUnit from slither.tools.doctor.utils import snip_section from slither.formatters.utils.patches import apply_patch, create_diff - +from slither.tools.mutator.utils.testing_generated_mutant import test_patch logger = logging.getLogger("Slither-Mutate") @@ -34,6 +34,8 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- HELP = "" FAULTCLASS = FaultClass.Undefined FAULTNATURE = FaultNature.Undefined + VALID_MUTANTS_COUNT = 0 + INVALID_MUTANTS_COUNT = 0 def __init__( self, compilation_unit: SlitherCompilationUnit, rate: int = 10, seed: Optional[int] = None @@ -73,13 +75,18 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- """TODO Documentation""" return {} - def mutate(self, testing_command: str, testing_directory: str, contract_name: str) -> Tuple[(int, int)]: + def mutate(self, testing_command: str, testing_directory: str, contract_name: str) -> Tuple[int, int]: + # identify the main contract, ignore the imports + for contract in self.slither.contracts: + if contract_name == str(contract.name): + self.contract = contract + # call _mutate function from different mutators - (all_patches, valid_mutant_count, invalid_mutant_count) = self._mutate(testing_command, testing_directory, contract_name) - + (all_patches) = self._mutate() + if "patches" not in all_patches: logger.debug(f"No patches found by {self.NAME}") - return + return (0,0) for file in all_patches["patches"]: original_txt = self.slither.source_code[file].encode("utf8") @@ -87,18 +94,27 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- offset = 0 patches = all_patches["patches"][file] patches.sort(key=lambda x: x["start"]) - if not all(patches[i]["end"] <= patches[i + 1]["end"] for i in range(len(patches) - 1)): - logger.info(f"Impossible to generate patch; patches collisions: {patches}") - continue + # if not all(patches[i]["end"] <= patches[i + 1]["end"] for i in range(len(patches) - 1)): + # logger.error(f"Impossible to generate patch; patches collisions: {patches}") + # continue for patch in patches: - patched_txt, offset = apply_patch(patched_txt, patch, offset) - diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) - if not diff: - logger.info(f"Impossible to generate patch; empty {patches}") + # print(patch) + # test the patch + flag = test_patch(file, patch, testing_command, self.VALID_MUTANTS_COUNT, self.NAME) + # count the valid and invalid mutants + if not flag: + self.INVALID_MUTANTS_COUNT += 1 + continue + self.VALID_MUTANTS_COUNT += 1 + # patched_txt, offset = apply_patch(patched_txt, patch, offset) + # diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) + # if not diff: + # logger.info(f"Impossible to generate patch; empty {patches}") + # print the differences - print(diff) + # print(diff) - return (valid_mutant_count, invalid_mutant_count) + return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 5a9465c86..4b0c3b1ad 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -1,4 +1,9 @@ # pylint: disable=unused-import # from slither.tools.mutator.mutators.MVIV import MVIV # from slither.tools.mutator.mutators.MVIE import MVIE -from slither.tools.mutator.mutators.MIA import MIA +# from slither.tools.mutator.mutators.MIA import MIA +from slither.tools.mutator.mutators.ROR import ROR +# from slither.tools.mutator.mutators.LOR import LOR +# from slither.tools.mutator.mutators.UOI import UOI +# from slither.tools.mutator.mutators.SBR import SBR + diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index c041f76d6..70f7deb11 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -4,9 +4,10 @@ import logging logger = logging.getLogger("Slither-Mutate") +duplicated_files = {} + # function to backup the source file def backup_source_file(source_code: Dict, output_folder: str) -> Dict: - duplicated_files = {} os.makedirs(output_folder, exist_ok=True) for file_path, content in source_code.items(): @@ -23,7 +24,8 @@ def backup_source_file(source_code: Dict, output_folder: str) -> Dict: # function to transfer the original content to the sol file after campaign def transfer_and_delete(files_dict: Dict) -> None: try: - for item, value in files_dict.items(): + files_dict_copy = files_dict.copy() + for item, value in files_dict_copy.items(): with open(value, 'r') as duplicated_file: content = duplicated_file.read() @@ -31,6 +33,10 @@ def transfer_and_delete(files_dict: Dict) -> None: original_file.write(content) os.remove(value) + + # delete elements from the global dict + del duplicated_files[item] + except Exception as e: logger.error(f"Error transferring content: {e}") @@ -45,14 +51,36 @@ def create_mutant_file(file: str, count: int, rule: str) -> None: # Write content to the original file mutant_name = filename.split('.')[0] + # create folder for each contract os.makedirs("mutation_campaign/" + mutant_name, exist_ok=True) - with open("mutation_campaign/" + mutant_name + '/' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: + with open("mutation_campaign/" + mutant_name + '/' + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: mutant_file.write(content) + # reset the file + with open(duplicated_files[file], 'r') as duplicated_file: + duplicate_content = duplicated_file.read() + + with open(file, 'w') as source_file: + source_file.write(duplicate_content) + except Exception as e: logger.error(f"Error creating mutant: {e}") +# function to reset the file +def reset_file(file: str) -> None: + try: + # directory, filename = os.path.split(file) + # reset the file + with open(duplicated_files[file], 'r') as duplicated_file: + duplicate_content = duplicated_file.read() + + with open(file, 'w') as source_file: + source_file.write(duplicate_content) + + except Exception as e: + logger.error(f"Error resetting file: {e}") + # function to get the contracts list def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str]: sol_file_list = [] diff --git a/slither/tools/mutator/utils/generic_patching.py b/slither/tools/mutator/utils/generic_patching.py index 03ccadec7..6c0ba6511 100644 --- a/slither/tools/mutator/utils/generic_patching.py +++ b/slither/tools/mutator/utils/generic_patching.py @@ -8,7 +8,7 @@ from slither.tools.mutator.utils.testing_generated_mutant import compile_generat from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file from slither.tools.mutator.utils.file_handling import create_mutant_file -def remove_assignement(variable: Variable, contract: Contract, result: Dict, test_cmd: str, test_dir: str) -> bool: +def remove_assignement(variable: Variable, contract: Contract, result: Dict) -> bool: """ Remove the variable's initial assignement @@ -28,19 +28,13 @@ def remove_assignement(variable: Variable, contract: Contract, result: Dict, tes old_str = in_file_str[start:stop] new_str = old_str[: old_str.find("=")] - - replace_string_in_source_file(in_file, in_file_str[variable.source_mapping.start + old_str.find("="):variable.source_mapping.end], '') - - # compile and run tests before the mutant generated before patching - if compile_generated_mutant(in_file): - if run_test_suite(test_cmd, test_dir): - # create_mutant_file(in_file, ) - create_patch( - result, - in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - ) - return True \ No newline at end of file + line_no = [0] + create_patch( + result, + in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no + ) \ No newline at end of file diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 61b9db214..7ab406519 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -2,8 +2,13 @@ import crytic_compile import subprocess import os import logging - +import time +import signal +from typing import List, Dict +from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_file +from slither.utils.colors import green, red logger = logging.getLogger("Slither-Mutate") +timeout = 30 # we can get it as parameter # function to compile the generated mutant def compile_generated_mutant(file_path: str) -> bool: @@ -11,7 +16,9 @@ def compile_generated_mutant(file_path: str) -> bool: crytic_compile.CryticCompile(file_path) return True except Exception as e: # pylint: disable=broad-except - logger.error("Error Crytic Compile", e) + print(True) + # logger.error("Error Crytic Compile") + return False # function to run the tests def run_test_suite(cmd: str, dir: str) -> bool: @@ -21,14 +28,55 @@ def run_test_suite(cmd: str, dir: str) -> bool: result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # result = subprocess.run(cmd.split(' '), check=True) - print(result.stdout) if not result.stderr: return True except subprocess.CalledProcessError as e: - print(e.output) logger.error(f"Error executing '{cmd}': {e}") return False except Exception as e: logger.error(f"An unexpected error occurred: {e}") - return False \ No newline at end of file + return False + +def run_test_cmd(cmd: str, dir: str) -> bool: + start = time.time() + + # starting new process + P = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid) + + try: + # checking whether the process is completed or not for 30 seconds + while P.poll() is None and (time.time() - start) < timeout: + time.sleep(0.05) + finally: + if P.poll() is None: + print() + print("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") + # sends a SIGTERM signal to process group - bascially killing the process + os.killpg(os.getpgid(P.pid), signal.SIGTERM) + # Avoid any weird race conditions from grabbing the return code + time.sleep(0.05) + # indicates whether the command executed sucessfully or not + r = P.returncode + + # if r is 0 then it is valid mutant because tests didn't fail + return True if r == 0 else False + +def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str) -> bool: + with open(file, 'r') as filepath: + content = filepath.read() + # Perform the replacement based on the index values + replaced_content = content[:patch['start']] + patch['new_string'] + content[patch['end']:] + + # Write the modified content back to the file + with open(file, 'w') as filepath: + filepath.write(replaced_content) + if(compile_generated_mutant(file)): + if(run_test_cmd(command, file)): + create_mutant_file(file, index, generator_name) + logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' in '{file}' ---> VALID\n")) + return True + + reset_file(file) + logger.info(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' in '{file}' ---> INVALID\n")) + return False \ No newline at end of file From 67b95dff7440c807e168c4796c37948810d0d77a Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Tue, 9 Jan 2024 12:03:22 -0500 Subject: [PATCH 15/64] Added new mutators --- slither/tools/mutator/__main__.py | 33 ++++++---- slither/tools/mutator/mutators/AOR.py | 38 ++++++++++++ slither/tools/mutator/mutators/ASOR.py | 50 +++++++++++++++ slither/tools/mutator/mutators/BOR.py | 35 +++++++++++ slither/tools/mutator/mutators/LOR.py | 14 +---- slither/tools/mutator/mutators/MIA.py | 20 +++--- slither/tools/mutator/mutators/MVIE.py | 45 +++++++++++--- slither/tools/mutator/mutators/MVIV.py | 45 +++++++++++--- slither/tools/mutator/mutators/MWA.py | 34 +++++++++++ slither/tools/mutator/mutators/ROR.py | 20 ++---- slither/tools/mutator/mutators/SBR.py | 22 +++---- slither/tools/mutator/mutators/UOI.py | 61 +++++++++---------- .../mutator/mutators/abstract_mutator.py | 25 +++++--- .../tools/mutator/mutators/all_mutators.py | 16 +++-- .../tools/mutator/utils/generic_patching.py | 40 ------------ .../tools/mutator/utils/replace_conditions.py | 48 --------------- .../mutator/utils/testing_generated_mutant.py | 13 ++-- 17 files changed, 339 insertions(+), 220 deletions(-) create mode 100644 slither/tools/mutator/mutators/AOR.py create mode 100644 slither/tools/mutator/mutators/ASOR.py create mode 100644 slither/tools/mutator/mutators/BOR.py create mode 100644 slither/tools/mutator/mutators/MWA.py delete mode 100644 slither/tools/mutator/utils/generic_patching.py delete mode 100644 slither/tools/mutator/utils/replace_conditions.py diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 201b39acd..aba427355 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -59,11 +59,18 @@ def parse_args() -> argparse.Namespace: help="Directories to ignore" ) - # to_do: add time out argument + # time out argument parser.add_argument( "--timeout", - help="Set timeout for test command" + help="Set timeout for test command (by deafult 30 seconds)" ) + + # output directory argument + parser.add_argument( + "--output-dir", + help="Output Directory (by default it is 'mutation_campaign')" + ) + # Initiate all the crytic config cli options cryticparser.init(parser) @@ -98,13 +105,13 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def main() -> None: args = parse_args() - # print(os.path.isdir(args.codebase)) # provided file/folder # arguments test_command: str = args.test_cmd test_directory: str = args.test_dir paths_to_ignore: str | None = args.ignore_dirs - timeout: int = args.timeout + output_dir: str | None = args.output_dir + timeout: int | None = args.timeout print(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) @@ -118,33 +125,33 @@ def main() -> None: sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore_list) # folder where backup files and valid mutants created - output_folder = os.getcwd() + "/mutation_campaign" + if output_dir == None: + output_dir = "/mutation_campaign" + output_folder = os.getcwd() + output_dir if os.path.exists(output_folder): shutil.rmtree(output_folder) + # set default timeout + if timeout == None: + timeout = 30 + for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] # slither object sl = Slither(filename, **vars(args)) - # create a backup files files_dict = backup_source_file(sl.source_code, output_folder) - # total count of mutants total_count = 0 - # count of valid mutants v_count = 0 # mutation try: for compilation_unit_of_main_file in sl.compilation_units: - # compilation_unit_of_main_file = sl.compilation_units[-1] - # for i in compilation_unit_of_main_file.contracts: - # print(i.name) for M in _get_mutators(): - m = M(compilation_unit_of_main_file) - count_valid, count_invalid = m.mutate(test_command, test_directory, contract_name) + m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name) + count_valid, count_invalid = m.mutate() v_count += count_valid total_count += count_valid + count_invalid except Exception as e: diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py new file mode 100644 index 000000000..f248d3c77 --- /dev/null +++ b/slither/tools/mutator/mutators/AOR.py @@ -0,0 +1,38 @@ +from typing import Dict +from slither.slithir.operations import Binary, BinaryType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass + +arithmetic_operators = [ + BinaryType.ADDITION, + BinaryType.DIVISION, + BinaryType.MULTIPLICATION, + BinaryType.SUBTRACTION, + BinaryType.MODULO +] + +class AOR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "AOR" + HELP = "Arithmetic operator replacement" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + for ir in node.irs: + if isinstance(ir, Binary) and ir.type in arithmetic_operators: + alternative_ops = arithmetic_operators[:] + alternative_ops.remove(ir.type) + for op in alternative_ops: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py new file mode 100644 index 000000000..8c70756a2 --- /dev/null +++ b/slither/tools/mutator/mutators/ASOR.py @@ -0,0 +1,50 @@ +from typing import Dict +from slither.slithir.operations import Binary, BinaryType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation + +assignment_operators = [ + AssignmentOperationType.ASSIGN_ADDITION, + AssignmentOperationType.ASSIGN_SUBTRACTION, + AssignmentOperationType.ASSIGN, + AssignmentOperationType.ASSIGN_OR, + AssignmentOperationType.ASSIGN_CARET, + AssignmentOperationType.ASSIGN_AND, + AssignmentOperationType.ASSIGN_LEFT_SHIFT, + AssignmentOperationType.ASSIGN_RIGHT_SHIFT, + AssignmentOperationType.ASSIGN_MULTIPLICATION, + AssignmentOperationType.ASSIGN_DIVISION, + AssignmentOperationType.ASSIGN_MODULO +] + +class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "ASOR" + HELP = "Assignment Operator Replacement" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + for ir in node.irs: + if isinstance(ir.expression, AssignmentOperation) and ir.expression.type in assignment_operators: + if ir.expression.type == AssignmentOperationType.ASSIGN: + continue + alternative_ops = assignment_operators[:] + try: + alternative_ops.remove(ir.expression.type) + except: + continue + for op in assignment_operators: + if op != ir.expression: + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py new file mode 100644 index 000000000..7878a20ea --- /dev/null +++ b/slither/tools/mutator/mutators/BOR.py @@ -0,0 +1,35 @@ +from typing import Dict +from slither.slithir.operations import Binary, BinaryType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass + +bitwise_operators = [ + BinaryType.AND, + BinaryType.OR +] + +class BOR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "BOR" + HELP = "Bitwise Operator Replacement" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + for ir in node.irs: + if isinstance(ir, Binary) and ir.type in bitwise_operators: + alternative_ops = bitwise_operators[:] + alternative_ops.remove(ir.type) + for op in alternative_ops: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index 382a08aee..b00b13000 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -15,17 +15,9 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} - contract = self.contract - - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] - for function in contract.functions_and_modifiers_declared: - + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in logical_operators: @@ -37,11 +29,11 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines # Replace the expression with true # new_str = f"{ir.variable_left} {op.value} {ir.variable_right}" new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index d76369d4d..1cc0fdb6d 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -2,6 +2,7 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" @@ -10,32 +11,31 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} - # Retrieve the file - in_file = self.contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = self.contract.compilation_unit.core.source_code[in_file] - for function in self.contract.functions_declared + list(self.contract.modifiers_declared): + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: if node.type == NodeType.IF: - # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines # Replace the expression with true and false for value in ["true", "false"]: new_str = value - create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + # print(node.expression) + if not isinstance(node.expression, UnaryOperation): + new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result - +# limitations - won't work if it is tenary operation \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 15b2a20c3..13a4e6d1a 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -1,9 +1,8 @@ from typing import Dict - from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass -from slither.tools.mutator.utils.generic_patching import remove_assignement +from slither.formatters.utils.patches import create_patch class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" @@ -12,24 +11,52 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} variable: Variable - contract = self.contract # Create fault for state variables declaration - for variable in contract.state_variables_declared: + for variable in self.contract.state_variables_declared: if variable.initialized: # Cannot remove the initialization of constant variables if variable.is_constant: continue if not isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) - - for function in contract.functions_declared + list(contract.modifiers_declared): + # Get the string + start = variable.source_mapping.start + stop = variable.expression.source_mapping.start + old_str = self.in_file_str[start:stop] + + new_str = old_str[: old_str.find("=")] + line_no = [0] + create_patch( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no + ) + + for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: if variable.initialized and not isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) + # Get the string + start = variable.source_mapping.start + stop = variable.expression.source_mapping.start + old_str = self.in_file_str[start:stop] + + new_str = old_str[: old_str.find("=")] + line_no = [0] + create_patch( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no + ) return result diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index 5e7c0a6e1..e705ff94a 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -1,9 +1,9 @@ -from typing import Dict, Tuple +from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass -from slither.tools.mutator.utils.generic_patching import remove_assignement +from slither.formatters.utils.patches import create_patch class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" @@ -12,24 +12,51 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} variable: Variable - contract = self.contract - + # Create fault for state variables declaration - for variable in contract.state_variables_declared: + for variable in self.contract.state_variables_declared: if variable.initialized: # Cannot remove the initialization of constant variables if variable.is_constant: continue if isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) + # Get the string + start = variable.source_mapping.start + stop = variable.expression.source_mapping.start + old_str = self.in_file_str[start:stop] - for function in contract.functions_declared + list(contract.modifiers_declared): + new_str = old_str[: old_str.find("=")] + line_no = [0] + create_patch( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no + ) + + for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: if variable.initialized and isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) + start = variable.source_mapping.start + stop = variable.expression.source_mapping.start + old_str = self.in_file_str[start:stop] + + new_str = old_str[: old_str.find("=")] + line_no = [0] + create_patch( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no + ) return result diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py new file mode 100644 index 000000000..1e2067425 --- /dev/null +++ b/slither/tools/mutator/mutators/MWA.py @@ -0,0 +1,34 @@ +from typing import Dict +from slither.core.cfg.node import NodeType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation + +class MWA(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "MIA" + HELP = '"while" construct around statement' + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + if node.type == NodeType.IFLOOP: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + + if not isinstance(node.expression, UnaryOperation): + new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result + + + +# limitations - won't work if it is tenary operation + + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index 9a8942e19..6a2ef6426 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -1,5 +1,4 @@ from typing import Dict -from collections import defaultdict from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass @@ -22,19 +21,11 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} - # result["patches"] = defaultdict(list) - contract = self.contract - for function in contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: - # Retrieve the file - in_file = self.contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = self.contract.compilation_unit.core.source_code[in_file] - if isinstance(ir, Binary) and ir.type in relational_operators: alternative_ops = relational_operators[:] alternative_ops.remove(ir.type) @@ -43,11 +34,12 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) - - return result \ No newline at end of file + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result + +# failing in case of condition1 || condition2 \ No newline at end of file diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index ac35d9540..6797c0c35 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -3,6 +3,7 @@ from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass import re +from slither.core.variables.variable import Variable solidity_rules = [ "abi\.encode\( ==> abi.encodePacked(", @@ -38,7 +39,8 @@ solidity_rules = [ "(u?)int32 ==> \\1int16", "(u?)int64 ==> \\1int32", "(u?)int128 ==> \\1int64", - "(u?)int256 ==> \\1int128" + "(u?)int256 ==> \\1int128" + "while ==> if", ] @@ -51,40 +53,36 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - contract = self.contract - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] + variable: Variable - for function in contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: if node.type != NodeType.ENTRYPOINT: # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines for value in solidity_rules: left_value = value.split(" ==> ")[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) != None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - for variable in contract.state_variables_declared: + for variable in self.contract.state_variables_declared: node = variable.node_initialization if node: start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines for value in solidity_rules: left_value = value.split(" ==> ")[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) != None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/UOI.py b/slither/tools/mutator/mutators/UOI.py index 6d5862e76..60e8c22c3 100644 --- a/slither/tools/mutator/mutators/UOI.py +++ b/slither/tools/mutator/mutators/UOI.py @@ -1,23 +1,19 @@ from typing import Dict -import re -from slither.core.expressions.unary_operation import UnaryOperationType +from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation +from slither.core.expressions.expression import Expression from slither.slithir.variables import Constant from slither.core.variables.local_variable import LocalVariable -from slither.core.expressions.expression import Expression from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass -from slither.core.cfg.node import NodeType - unary_operators = [ UnaryOperationType.PLUSPLUS_PRE, UnaryOperationType.MINUSMINUS_PRE, UnaryOperationType.PLUSPLUS_POST, UnaryOperationType.MINUSMINUS_POST, - UnaryOperationType.MINUS_PRE, + UnaryOperationType.MINUS_PRE ] - class UOI(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "UOI" HELP = "Unary operator insertion" @@ -25,32 +21,35 @@ class UOI(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} - contract = self.contract - - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] - - for function in contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if (node.type == NodeType.EXPRESSION): + try: + ir_expression = node.expression + except Exception as e: + continue + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + if isinstance(ir_expression, UnaryOperation) and ir_expression.type in unary_operators: for op in unary_operators: - if str(op) in str(node.expression): - for i in node.variables_written: - print(i) - # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] - # print(old_str) - # Replace the expression with true - # new_str = old_str.replace(str(operand), f"{str(op)}{operand}") - # new_str = re.sub(r'(\w+)\+\+', r'++\1', text) - # print(new_str) - # create_patch(result, in_file, start, stop, old_str, new_str) - print(result) + if not node.expression.is_prefix: + if node.expression.type != op: + variable_read = node.variables_read[0] + new_str = str(variable_read) + str(op) + if new_str != old_str: + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(op) + str(variable_read) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + else: + if node.expression.type != op: + variable_read = node.variables_read[0] + new_str = str(op) + str(variable_read) + if new_str != old_str: + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(variable_read) + str(op) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index e58b705a1..ead78ac97 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -38,12 +38,15 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- INVALID_MUTANTS_COUNT = 0 def __init__( - self, compilation_unit: SlitherCompilationUnit, rate: int = 10, seed: Optional[int] = None + self, compilation_unit: SlitherCompilationUnit, timeout: int, testing_command: str, testing_directory: str, contract_name: str, rate: int = 10, seed: Optional[int] = None ): self.compilation_unit = compilation_unit self.slither = compilation_unit.core self.seed = seed self.rate = rate + self.test_command = testing_command + self.test_directory = testing_directory + self.timeout = timeout if not self.NAME: raise IncorrectMutatorInitialization( @@ -69,18 +72,23 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- raise IncorrectMutatorInitialization( f"rate must be between 0 and 100 {self.__class__.__name__}" ) + + # identify the main contract, ignore the imports + for contract in self.slither.contracts: + if contract_name == str(contract.name): # limitation: what if the contract name is not same as file name + # contract + self.contract = contract + # Retrieve the file + self.in_file = self.contract.source_mapping.filename.absolute + # Retrieve the source code + self.in_file_str = self.contract.compilation_unit.core.source_code[self.in_file] @abc.abstractmethod def _mutate(self, test_cmd: str, test_dir: str) -> Dict: """TODO Documentation""" return {} - def mutate(self, testing_command: str, testing_directory: str, contract_name: str) -> Tuple[int, int]: - # identify the main contract, ignore the imports - for contract in self.slither.contracts: - if contract_name == str(contract.name): - self.contract = contract - + def mutate(self) -> Tuple[int, int]: # call _mutate function from different mutators (all_patches) = self._mutate() @@ -98,9 +106,8 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # logger.error(f"Impossible to generate patch; patches collisions: {patches}") # continue for patch in patches: - # print(patch) # test the patch - flag = test_patch(file, patch, testing_command, self.VALID_MUTANTS_COUNT, self.NAME) + flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout) # count the valid and invalid mutants if not flag: self.INVALID_MUTANTS_COUNT += 1 diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 4b0c3b1ad..3f4e59043 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -1,9 +1,13 @@ # pylint: disable=unused-import -# from slither.tools.mutator.mutators.MVIV import MVIV -# from slither.tools.mutator.mutators.MVIE import MVIE -# from slither.tools.mutator.mutators.MIA import MIA +from slither.tools.mutator.mutators.MVIV import MVIV +from slither.tools.mutator.mutators.MVIE import MVIE +from slither.tools.mutator.mutators.MIA import MIA from slither.tools.mutator.mutators.ROR import ROR -# from slither.tools.mutator.mutators.LOR import LOR -# from slither.tools.mutator.mutators.UOI import UOI -# from slither.tools.mutator.mutators.SBR import SBR +from slither.tools.mutator.mutators.LOR import LOR +from slither.tools.mutator.mutators.UOI import UOI +from slither.tools.mutator.mutators.SBR import SBR +from slither.tools.mutator.mutators.AOR import AOR +from slither.tools.mutator.mutators.BOR import BOR +from slither.tools.mutator.mutators.ASOR import ASOR +from slither.tools.mutator.mutators.MWA import MWA diff --git a/slither/tools/mutator/utils/generic_patching.py b/slither/tools/mutator/utils/generic_patching.py deleted file mode 100644 index 6c0ba6511..000000000 --- a/slither/tools/mutator/utils/generic_patching.py +++ /dev/null @@ -1,40 +0,0 @@ -from typing import Dict -import os - -from slither.core.declarations import Contract -from slither.core.variables.variable import Variable -from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.utils.testing_generated_mutant import compile_generated_mutant, run_test_suite -from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file -from slither.tools.mutator.utils.file_handling import create_mutant_file - -def remove_assignement(variable: Variable, contract: Contract, result: Dict) -> bool: - """ - Remove the variable's initial assignement - - :param variable: - :param contract: - :param result: - :return: - """ - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] - - # Get the string - start = variable.source_mapping.start - stop = variable.expression.source_mapping.start - old_str = in_file_str[start:stop] - - new_str = old_str[: old_str.find("=")] - line_no = [0] - create_patch( - result, - in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - line_no - ) \ No newline at end of file diff --git a/slither/tools/mutator/utils/replace_conditions.py b/slither/tools/mutator/utils/replace_conditions.py deleted file mode 100644 index 4e3f91454..000000000 --- a/slither/tools/mutator/utils/replace_conditions.py +++ /dev/null @@ -1,48 +0,0 @@ -import logging -import re - -logger = logging.getLogger("Slither-Mutate") - -# function to replace the string -def replace_string_in_source_file(file_path: str, old_string: str, new_string: str) -> None: - try: - # Read the content of the Solidity file - with open(file_path, 'r') as file: - content = file.read() - - # Perform the string replacement - modified_content = content.replace(old_string, new_string) - - # Write the modified content back to the file - with open(file_path, 'w') as file: - file.write(modified_content) - - logger.info(f"String '{old_string}' replaced with '{new_string}' in '{file_path}'.") - except Exception as e: - logger.error(f"Error replacing string: {e}") - -# function to replace the string in a specific line -def replace_string_in_source_file_specific_line(file_path: str, old_string: str, new_string: str, line_number : int) -> None: - try: - # Read the content of the Solidity file - with open(file_path, 'r') as file: - lines = file.readlines() - - if 1 <= line_number <= len(lines): - # remove the spaces in the string - line = lines[line_number - 1].replace(" ", "") - old_string = old_string.replace(" ", "") - - # Replace the old string with the new string on the specified line - lines[line_number - 1] = line.replace(old_string.strip(), new_string) - - # Write the modified content back to the file - with open(file_path, 'w') as file: - file.writelines(lines) - - logger.info(f"String '{old_string}' replaced with '{new_string}' in '{file_path}'.' at '{line_number}") - else: - logger.error(f'Error: Line number {line_number} is out of range') - - except Exception as e: - logger.erro(f'Error: {e}') \ No newline at end of file diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 7ab406519..61a688f7c 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -38,14 +38,12 @@ def run_test_suite(cmd: str, dir: str) -> bool: logger.error(f"An unexpected error occurred: {e}") return False -def run_test_cmd(cmd: str, dir: str) -> bool: +def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: start = time.time() - # starting new process P = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid) - try: - # checking whether the process is completed or not for 30 seconds + # checking whether the process is completed or not within 30 seconds(default) while P.poll() is None and (time.time() - start) < timeout: time.sleep(0.05) finally: @@ -58,21 +56,20 @@ def run_test_cmd(cmd: str, dir: str) -> bool: time.sleep(0.05) # indicates whether the command executed sucessfully or not r = P.returncode - + # if r is 0 then it is valid mutant because tests didn't fail return True if r == 0 else False -def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str) -> bool: +def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int) -> bool: with open(file, 'r') as filepath: content = filepath.read() # Perform the replacement based on the index values replaced_content = content[:patch['start']] + patch['new_string'] + content[patch['end']:] - # Write the modified content back to the file with open(file, 'w') as filepath: filepath.write(replaced_content) if(compile_generated_mutant(file)): - if(run_test_cmd(command, file)): + if(run_test_cmd(command, file, timeout)): create_mutant_file(file, index, generator_name) logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' in '{file}' ---> VALID\n")) return True From df42cb66d18af3132c326b26759ce670144ad7e2 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Sun, 14 Jan 2024 19:19:58 -0500 Subject: [PATCH 16/64] Updated mutators --- slither/tools/mutator/__main__.py | 48 +++++++---- slither/tools/mutator/mutators/AOR.py | 10 ++- slither/tools/mutator/mutators/ASOR.py | 6 +- slither/tools/mutator/mutators/BOR.py | 8 +- slither/tools/mutator/mutators/FHR.py | 36 ++++++++ slither/tools/mutator/mutators/LIR.py | 82 ++++++++++++++++++ slither/tools/mutator/mutators/LOR.py | 7 +- slither/tools/mutator/mutators/MIA.py | 18 ++-- slither/tools/mutator/mutators/MVIE.py | 11 ++- slither/tools/mutator/mutators/MVIV.py | 13 ++- slither/tools/mutator/mutators/MWA.py | 13 +-- slither/tools/mutator/mutators/RCR.py | 36 ++++++++ slither/tools/mutator/mutators/ROR.py | 34 ++++---- slither/tools/mutator/mutators/SBR.py | 9 +- .../tools/mutator/mutators/{UOI.py => UOR.py} | 18 ++-- .../mutator/mutators/abstract_mutator.py | 86 +++++++++++-------- .../tools/mutator/mutators/all_mutators.py | 26 +++--- slither/tools/mutator/utils/command_line.py | 11 ++- slither/tools/mutator/utils/file_handling.py | 4 +- .../mutator/utils/testing_generated_mutant.py | 58 +++++++------ 20 files changed, 351 insertions(+), 183 deletions(-) create mode 100644 slither/tools/mutator/mutators/FHR.py create mode 100644 slither/tools/mutator/mutators/LIR.py create mode 100644 slither/tools/mutator/mutators/RCR.py rename slither/tools/mutator/mutators/{UOI.py => UOR.py} (80%) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index aba427355..c41a82e35 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -2,12 +2,10 @@ import argparse import inspect import logging import sys -from typing import Type, List, Any, Dict, Tuple import os import shutil - +from typing import Type, List, Any from crytic_compile import cryticparser - from slither import Slither from slither.tools.mutator.mutators import all_mutators from .mutators.abstract_mutator import AbstractMutator @@ -62,13 +60,27 @@ def parse_args() -> argparse.Namespace: # time out argument parser.add_argument( "--timeout", - help="Set timeout for test command (by deafult 30 seconds)" + help="Set timeout for test command (by default 30 seconds)" ) # output directory argument parser.add_argument( "--output-dir", - help="Output Directory (by default it is 'mutation_campaign')" + help="Output Directory (by default 'mutation_campaign')" + ) + + # to print just all the mutants + parser.add_argument( + "--verbose", + help="output all mutants generated", + action="store_true", + default=False, + ) + + # select list of mutators to run + parser.add_argument( + "--mutators-to-run", + help="mutant generators to run", ) # Initiate all the crytic config cli options @@ -80,13 +92,14 @@ def parse_args() -> argparse.Namespace: return parser.parse_args() - -def _get_mutators() -> List[Type[AbstractMutator]]: +def _get_mutators(mutators_list: List[str] | None) -> List[Type[AbstractMutator]]: detectors_ = [getattr(all_mutators, name) for name in dir(all_mutators)] - detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator)] + if not mutators_list is None: + detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) and str(c.NAME) in mutators_list ] + else: + detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) ] return detectors - class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def __call__( self, parser: Any, *args: Any, **kwargs: Any @@ -105,13 +118,15 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def main() -> None: args = parse_args() - # arguments test_command: str = args.test_cmd test_directory: str = args.test_dir paths_to_ignore: str | None = args.ignore_dirs output_dir: str | None = args.output_dir timeout: int | None = args.timeout + solc_remappings: str | None = args.solc_remaps + verbose: bool = args.verbose + mutators_to_run: List[str] | None = args.mutators_to_run print(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) @@ -137,6 +152,7 @@ def main() -> None: for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] + # TODO: user provides contract name # slither object sl = Slither(filename, **vars(args)) # create a backup files @@ -149,11 +165,13 @@ def main() -> None: # mutation try: for compilation_unit_of_main_file in sl.compilation_units: - for M in _get_mutators(): - m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name) - count_valid, count_invalid = m.mutate() - v_count += count_valid - total_count += count_valid + count_invalid + for M in _get_mutators(mutators_to_run): + m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name, solc_remappings, verbose, output_folder) + # check whether the contract instance exists or not + if m.get_exist_flag(): + count_valid, count_invalid = m.mutate() + v_count += count_valid + total_count += count_valid + count_invalid except Exception as e: logger.error(e) diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index f248d3c77..39e3a6a20 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -1,7 +1,8 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.core.expressions.unary_operation import UnaryOperation arithmetic_operators = [ BinaryType.ADDITION, @@ -14,7 +15,6 @@ arithmetic_operators = [ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "AOR" HELP = "Arithmetic operator replacement" - FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -22,8 +22,14 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: + try: + ir_expression = node.expression + except: + continue for ir in node.irs: if isinstance(ir, Binary) and ir.type in arithmetic_operators: + if isinstance(ir_expression, UnaryOperation): + continue alternative_ops = arithmetic_operators[:] alternative_ops.remove(ir.type) for op in alternative_ops: diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index 8c70756a2..04ad8f8b0 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -1,7 +1,6 @@ from typing import Dict -from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation assignment_operators = [ @@ -21,7 +20,6 @@ assignment_operators = [ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ASOR" HELP = "Assignment Operator Replacement" - FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -38,7 +36,7 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods alternative_ops.remove(ir.expression.type) except: continue - for op in assignment_operators: + for op in alternative_ops: if op != ir.expression: start = node.source_mapping.start stop = start + node.source_mapping.length diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index 7878a20ea..de9ad287e 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -1,17 +1,19 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature bitwise_operators = [ BinaryType.AND, - BinaryType.OR + BinaryType.OR, + BinaryType.LEFT_SHIFT, + BinaryType.RIGHT_SHIFT, + BinaryType.CARET ] class BOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "BOR" HELP = "Bitwise Operator Replacement" - FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py new file mode 100644 index 000000000..5709346b1 --- /dev/null +++ b/slither/tools/mutator/mutators/FHR.py @@ -0,0 +1,36 @@ +from typing import Dict +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +import re + +# INFO: low severity + +function_header_replacements = [ + "pure ==> view", + "view ==> pure", + "(\s)(external|public|internal) ==> \\1private", + "(\s)(external|public) ==> \\1internal" +] + +class FHR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "FHR" + HELP = 'Function Header Replacement' + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + # function_header = function.source_mapping.content.split('{')[0] + start = function.source_mapping.start + stop = start + function.source_mapping.content.find('{') + old_str = self.in_file_str[start:stop] + line_no = function.source_mapping.lines + for value in function_header_replacements: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py new file mode 100644 index 000000000..99228913a --- /dev/null +++ b/slither/tools/mutator/mutators/LIR.py @@ -0,0 +1,82 @@ +from typing import Dict +from slither.core.expressions import Literal +from slither.core.variables.variable import Variable +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.formatters.utils.patches import create_patch +from slither.core.solidity_types import ElementaryType + +literal_replacements = [] + +class LIR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "LIR" + HELP = "Literal Interger Replacement" + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + variable: Variable + + # Create fault for state variables declaration + for variable in self.contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue + + if isinstance(variable.expression, Literal): + if isinstance(variable.type, ElementaryType): + literal_replacements.append(variable.type.min) # append data type min value + literal_replacements.append(variable.type.max) # append data type max value + if str(variable.type).startswith("uint"): + literal_replacements.append('1') + elif str(variable.type).startswith("uint"): + literal_replacements.append('-1') + # Get the string + start = variable.source_mapping.start + stop = start + variable.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = variable.node_initialization.source_mapping.lines + # line_no = [0] + for value in literal_replacements: + old_value = old_str[old_str.find("=")+1:].strip() + if old_value != value: + new_str = f"{old_str.split('=')[0]}= {value}" + create_patch( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0] + ) + + for function in self.contract.functions_and_modifiers_declared: + for variable in function.local_variables: + if variable.initialized and isinstance(variable.expression, Literal): + if isinstance(variable.type, ElementaryType): + literal_replacements.append(variable.type.min) + literal_replacements.append(variable.type.max) + if str(variable.type).startswith("uint"): + literal_replacements.append('1') + elif str(variable.type).startswith("uint"): + literal_replacements.append('-1') + start = variable.source_mapping.start + stop = start + variable.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = variable.source_mapping.lines + for new_value in literal_replacements: + old_value = old_str[old_str.find("=")+1:].strip() + if old_value != new_value: + new_str = f"{old_str.split('=')[0]}= {new_value}" + create_patch( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0] + ) + + return result diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index b00b13000..fa66c7bca 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature logical_operators = [ BinaryType.OROR, @@ -10,8 +10,7 @@ logical_operators = [ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LOR" - HELP = "Logical operator replacement" - FAULTCLASS = FaultClass.Checking + HELP = "Logical Operator Replacement" FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -25,14 +24,12 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods alternative_ops.remove(ir.type) for op in alternative_ops: - # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines # Replace the expression with true - # new_str = f"{ir.variable_left} {op.value} {ir.variable_right}" new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 1cc0fdb6d..f5bc52b16 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" HELP = '"if" construct around statement' - FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -17,8 +16,8 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods for node in function.nodes: if node.type == NodeType.IF: # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length + start = node.expression.source_mapping.start + stop = start + node.expression.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines @@ -27,15 +26,10 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods new_str = value create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - # print(node.expression) if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - return result - - -# limitations - won't work if it is tenary operation - - \ No newline at end of file + print(node.expression) + + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 13a4e6d1a..3c334e9e6 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.formatters.utils.patches import create_patch class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" HELP = "variable initialization using an expression" - FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -28,7 +27,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] - line_no = [0] + line_no = variable.node_initialization.source_mapping.lines create_patch( result, self.in_file, @@ -36,7 +35,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no + line_no[0] ) for function in self.contract.functions_and_modifiers_declared: @@ -48,7 +47,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] - line_no = [0] + line_no = variable.source_mapping.lines create_patch( result, self.in_file, @@ -56,7 +55,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no + line_no[0] ) return result diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index e705ff94a..7f75b1dcf 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -2,13 +2,12 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.formatters.utils.patches import create_patch class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" HELP = "variable initialization using a value" - FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -27,9 +26,8 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods start = variable.source_mapping.start stop = variable.expression.source_mapping.start old_str = self.in_file_str[start:stop] - new_str = old_str[: old_str.find("=")] - line_no = [0] + line_no = variable.node_initialization.source_mapping.lines create_patch( result, self.in_file, @@ -37,7 +35,7 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no + line_no[0] ) for function in self.contract.functions_and_modifiers_declared: @@ -46,9 +44,8 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods start = variable.source_mapping.start stop = variable.expression.source_mapping.start old_str = self.in_file_str[start:stop] - new_str = old_str[: old_str.find("=")] - line_no = [0] + line_no = variable.source_mapping.lines create_patch( result, self.in_file, @@ -56,7 +53,7 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no + line_no[0] ) return result diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index 1e2067425..c6bacf485 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation class MWA(AbstractMutator): # pylint: disable=too-few-public-methods - NAME = "MIA" + NAME = "MWA" HELP = '"while" construct around statement' - FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -25,10 +24,4 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result - - - -# limitations - won't work if it is tenary operation - - \ No newline at end of file + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/RCR.py b/slither/tools/mutator/mutators/RCR.py new file mode 100644 index 000000000..96aebc68f --- /dev/null +++ b/slither/tools/mutator/mutators/RCR.py @@ -0,0 +1,36 @@ +from typing import Dict +from slither.core.cfg.node import NodeType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature + + +class RCR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "RCR" + HELP = 'Revert and Comment Replacement' + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + if node.type != NodeType.ENTRYPOINT and NodeType.ENDIF != node.type and NodeType.ENDLOOP != node.type: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + if old_str != 'revert()': + new_str = 'revert()' + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + new_str = "//" + old_str + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + return result + + + + + + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index 6a2ef6426..e1c78c1eb 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -1,8 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass - +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature relational_operators = [ BinaryType.LESS, @@ -13,11 +12,9 @@ relational_operators = [ BinaryType.NOT_EQUAL, ] - class ROR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ROR" - HELP = "Relational operator replacement" - FAULTCLASS = FaultClass.Checking + HELP = "Relational Operator Replacement" FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -27,19 +24,18 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in relational_operators: - alternative_ops = relational_operators[:] - alternative_ops.remove(ir.type) - - for op in alternative_ops: - # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length - old_str = self.in_file_str[start:stop] - line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if str(ir.variable_left.type) != 'address' and str(ir.variable_right) != 'address': + alternative_ops = relational_operators[:] + alternative_ops.remove(ir.type) + for op in alternative_ops: + # Get the string + start = ir.expression.source_mapping.start + stop = start + ir.expression.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" + + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result -# failing in case of condition1 || condition2 \ No newline at end of file diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index 6797c0c35..91c05b884 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature import re from slither.core.variables.variable import Variable @@ -39,15 +39,14 @@ solidity_rules = [ "(u?)int32 ==> \\1int16", "(u?)int64 ==> \\1int32", "(u?)int128 ==> \\1int64", - "(u?)int256 ==> \\1int128" - "while ==> if", + "(u?)int256 ==> \\1int128", + "while ==> if", ] class SBR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "SBR" - HELP = 'Solidity Based Replacements' - FAULTCLASS = FaultClass.Checking + HELP = 'Solidity Based Replacement' FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: diff --git a/slither/tools/mutator/mutators/UOI.py b/slither/tools/mutator/mutators/UOR.py similarity index 80% rename from slither/tools/mutator/mutators/UOI.py rename to slither/tools/mutator/mutators/UOR.py index 60e8c22c3..671ee676d 100644 --- a/slither/tools/mutator/mutators/UOI.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -1,10 +1,7 @@ from typing import Dict from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation -from slither.core.expressions.expression import Expression -from slither.slithir.variables import Constant -from slither.core.variables.local_variable import LocalVariable from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature unary_operators = [ UnaryOperationType.PLUSPLUS_PRE, @@ -14,10 +11,9 @@ unary_operators = [ UnaryOperationType.MINUS_PRE ] -class UOI(AbstractMutator): # pylint: disable=too-few-public-methods - NAME = "UOI" - HELP = "Unary operator insertion" - FAULTCLASS = FaultClass.Checking +class UOR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "UOR" + HELP = "Unary Operator Replacement" FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -27,7 +23,7 @@ class UOI(AbstractMutator): # pylint: disable=too-few-public-methods for node in function.nodes: try: ir_expression = node.expression - except Exception as e: + except: continue start = node.source_mapping.start stop = start + node.source_mapping.length @@ -39,7 +35,7 @@ class UOI(AbstractMutator): # pylint: disable=too-few-public-methods if node.expression.type != op: variable_read = node.variables_read[0] new_str = str(variable_read) + str(op) - if new_str != old_str: + if new_str != old_str and str(op) != '-': create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) new_str = str(op) + str(variable_read) create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) @@ -47,7 +43,7 @@ class UOI(AbstractMutator): # pylint: disable=too-few-public-methods if node.expression.type != op: variable_read = node.variables_read[0] new_str = str(op) + str(variable_read) - if new_str != old_str: + if new_str != old_str and str(op) != '-': create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) new_str = str(variable_read) + str(op) create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index ead78ac97..5223e2d81 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -1,45 +1,48 @@ import abc import logging from enum import Enum -from typing import Optional, Dict, Tuple, List - +from typing import Optional, Dict, Tuple from slither.core.compilation_unit import SlitherCompilationUnit -from slither.tools.doctor.utils import snip_section +# from slither.tools.doctor.utils import snip_section from slither.formatters.utils.patches import apply_patch, create_diff from slither.tools.mutator.utils.testing_generated_mutant import test_patch -logger = logging.getLogger("Slither-Mutate") +from slither.utils.colors import yellow +logger = logging.getLogger("Slither-Mutate") class IncorrectMutatorInitialization(Exception): pass - -class FaultClass(Enum): - Assignement = 0 - Checking = 1 - Interface = 2 - Algorithm = 3 - Undefined = 100 - - class FaultNature(Enum): Missing = 0 Wrong = 1 Extraneous = 2 Undefined = 100 - + # not executed - can be detected by replacing with revert + # has no effect - can be detected by removing a line / comment + # can have valid mutant + # can't have valid mutant + class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public-methods NAME = "" HELP = "" - FAULTCLASS = FaultClass.Undefined FAULTNATURE = FaultNature.Undefined VALID_MUTANTS_COUNT = 0 INVALID_MUTANTS_COUNT = 0 def __init__( - self, compilation_unit: SlitherCompilationUnit, timeout: int, testing_command: str, testing_directory: str, contract_name: str, rate: int = 10, seed: Optional[int] = None - ): + self, compilation_unit: SlitherCompilationUnit, + timeout: int, + testing_command: str, + testing_directory: str, + contract_name: str, + solc_remappings: str | None, + verbose: bool, + output_folder: str, + rate: int = 10, + seed: Optional[int] = None + ) -> None: self.compilation_unit = compilation_unit self.slither = compilation_unit.core self.seed = seed @@ -47,6 +50,10 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- self.test_command = testing_command self.test_directory = testing_directory self.timeout = timeout + self.contract_exist = False + self.solc_remappings = solc_remappings + self.verbose = verbose + self.output_folder = output_folder if not self.NAME: raise IncorrectMutatorInitialization( @@ -58,11 +65,6 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- f"HELP is not initialized {self.__class__.__name__}" ) - if self.FAULTCLASS == FaultClass.Undefined: - raise IncorrectMutatorInitialization( - f"FAULTCLASS is not initialized {self.__class__.__name__}" - ) - if self.FAULTNATURE == FaultNature.Undefined: raise IncorrectMutatorInitialization( f"FAULTNATURE is not initialized {self.__class__.__name__}" @@ -75,14 +77,25 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # identify the main contract, ignore the imports for contract in self.slither.contracts: - if contract_name == str(contract.name): # limitation: what if the contract name is not same as file name + # !limitation: what if the contract name is not same as file name + # !limitation: multi contract + if contract_name.lower() == str(contract.name).lower(): # contract self.contract = contract # Retrieve the file self.in_file = self.contract.source_mapping.filename.absolute # Retrieve the source code self.in_file_str = self.contract.compilation_unit.core.source_code[self.in_file] - + # flag contract existence + self.contract_exist = True + + if not self.contract_exist: + self.contract_exist = False + logger.error(f"Contract name is not matching with the File name ({contract_name}). Please refer 'https://docs.soliditylang.org/en/latest/style-guide.html#contract-and-library-names')") + + def get_exist_flag(self) -> bool: + return self.contract_exist + @abc.abstractmethod def _mutate(self, test_cmd: str, test_dir: str) -> Dict: """TODO Documentation""" @@ -95,31 +108,28 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- if "patches" not in all_patches: logger.debug(f"No patches found by {self.NAME}") return (0,0) - + for file in all_patches["patches"]: original_txt = self.slither.source_code[file].encode("utf8") - patched_txt = original_txt - offset = 0 patches = all_patches["patches"][file] patches.sort(key=lambda x: x["start"]) - # if not all(patches[i]["end"] <= patches[i + 1]["end"] for i in range(len(patches) - 1)): - # logger.error(f"Impossible to generate patch; patches collisions: {patches}") - # continue + print(yellow(f"Mutating {file} with {self.NAME} \n")) for patch in patches: # test the patch - flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout) + flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout, self.solc_remappings, self.verbose) # count the valid and invalid mutants if not flag: self.INVALID_MUTANTS_COUNT += 1 continue self.VALID_MUTANTS_COUNT += 1 - # patched_txt, offset = apply_patch(patched_txt, patch, offset) - # diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) - # if not diff: - # logger.info(f"Impossible to generate patch; empty {patches}") - - # print the differences - # print(diff) + patched_txt,_ = apply_patch(original_txt, patch, 0) + diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) + if not diff: + logger.info(f"Impossible to generate patch; empty {patches}") + + # add valid mutant patches to a output file + with open(self.output_folder + "/patches_file.txt", 'a') as patches_file: + patches_file.write(diff + '\n') return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 3f4e59043..9aa81a0fc 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -1,13 +1,17 @@ # pylint: disable=unused-import -from slither.tools.mutator.mutators.MVIV import MVIV -from slither.tools.mutator.mutators.MVIE import MVIE -from slither.tools.mutator.mutators.MIA import MIA -from slither.tools.mutator.mutators.ROR import ROR -from slither.tools.mutator.mutators.LOR import LOR -from slither.tools.mutator.mutators.UOI import UOI -from slither.tools.mutator.mutators.SBR import SBR -from slither.tools.mutator.mutators.AOR import AOR -from slither.tools.mutator.mutators.BOR import BOR -from slither.tools.mutator.mutators.ASOR import ASOR -from slither.tools.mutator.mutators.MWA import MWA +from slither.tools.mutator.mutators.MVIV import MVIV # severity low +from slither.tools.mutator.mutators.MVIE import MVIE # severity low +from slither.tools.mutator.mutators.LOR import LOR # severity medium +from slither.tools.mutator.mutators.UOR import UOR # severity medium +from slither.tools.mutator.mutators.SBR import SBR # severity medium +from slither.tools.mutator.mutators.AOR import AOR # severity medium +from slither.tools.mutator.mutators.BOR import BOR # severity medium +from slither.tools.mutator.mutators.ASOR import ASOR # severity medium +from slither.tools.mutator.mutators.MWA import MWA # severity medium +from slither.tools.mutator.mutators.LIR import LIR # severity medium +from slither.tools.mutator.mutators.FHR import FHR # severity medium +from slither.tools.mutator.mutators.MIA import MIA # severity medium +from slither.tools.mutator.mutators.ROR import ROR # severity medium +from slither.tools.mutator.mutators.RCR import RCR # severity high + diff --git a/slither/tools/mutator/utils/command_line.py b/slither/tools/mutator/utils/command_line.py index 80d610a69..042b4fff7 100644 --- a/slither/tools/mutator/utils/command_line.py +++ b/slither/tools/mutator/utils/command_line.py @@ -7,15 +7,14 @@ def output_mutators(mutators_classes: List[Type[AbstractMutator]]) -> None: for detector in mutators_classes: argument = detector.NAME help_info = detector.HELP - fault_class = detector.FAULTCLASS.name fault_nature = detector.FAULTNATURE.name - mutators_list.append((argument, help_info, fault_class, fault_nature)) - table = MyPrettyTable(["Num", "Name", "What it Does", "Fault Class", "Fault Nature"]) + mutators_list.append((argument, help_info, fault_nature)) + table = MyPrettyTable(["Num", "Name", "What it Does", "Fault Nature"]) # Sort by class, nature, name - mutators_list = sorted(mutators_list, key=lambda element: (element[2], element[3], element[0])) + mutators_list = sorted(mutators_list, key=lambda element: (element[2], element[0])) idx = 1 - for (argument, help_info, fault_class, fault_nature) in mutators_list: - table.add_row([str(idx), argument, help_info, fault_class, fault_nature]) + for (argument, help_info, fault_nature) in mutators_list: + table.add_row([str(idx), argument, help_info, fault_nature]) idx = idx + 1 print(table) diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index 70f7deb11..d61bba58a 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -105,5 +105,5 @@ def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str sol_file_list.append(i) return sol_file_list -# to_do: create a function to delete the commands from the sol file -# def remove_comments(self) -> None: \ No newline at end of file + +# TODO: create a function to delete the commands from the sol file diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 61a688f7c..6c6e80a55 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -7,38 +7,44 @@ import signal from typing import List, Dict from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_file from slither.utils.colors import green, red + logger = logging.getLogger("Slither-Mutate") -timeout = 30 # we can get it as parameter # function to compile the generated mutant -def compile_generated_mutant(file_path: str) -> bool: +def compile_generated_mutant(file_path: str, mappings: str) -> bool: try: - crytic_compile.CryticCompile(file_path) + crytic_compile.CryticCompile(file_path, solc_remaps=mappings) return True - except Exception as e: # pylint: disable=broad-except - print(True) + except: # pylint: disable=broad-except # logger.error("Error Crytic Compile") return False # function to run the tests -def run_test_suite(cmd: str, dir: str) -> bool: - try: - # Change to the foundry folder - # os.chdir(dir) +# def run_test_suite(cmd: str, dir: str) -> bool: +# try: +# # Change to the foundry folder +# # os.chdir(dir) - result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - # result = subprocess.run(cmd.split(' '), check=True) - if not result.stderr: - return True - except subprocess.CalledProcessError as e: - logger.error(f"Error executing '{cmd}': {e}") +# result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) +# # result = subprocess.run(cmd.split(' '), check=True) +# if not result.stderr: +# return True +# except subprocess.CalledProcessError as e: +# logger.error(f"Error executing '{cmd}': {e}") - return False - except Exception as e: - logger.error(f"An unexpected error occurred: {e}") - return False +# return False +# except Exception as e: +# logger.error(f"An unexpected error occurred: {e}") +# return False def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: + # add --fail-fast for foundry tests, to exit after first failure + if "forge test" in cmd and not "--fail-fast" in cmd : + cmd += " --fail-fast" + # add --bail for hardhat and truffle tests, to exit after first failure + elif not "--bail" in cmd: + cmd += " --bail" + start = time.time() # starting new process P = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid) @@ -48,19 +54,18 @@ def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: time.sleep(0.05) finally: if P.poll() is None: - print() - print("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") + logger.error("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") # sends a SIGTERM signal to process group - bascially killing the process os.killpg(os.getpgid(P.pid), signal.SIGTERM) # Avoid any weird race conditions from grabbing the return code time.sleep(0.05) # indicates whether the command executed sucessfully or not r = P.returncode - + # if r is 0 then it is valid mutant because tests didn't fail return True if r == 0 else False -def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int) -> bool: +def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int, mappings: str | None, verbose: bool) -> bool: with open(file, 'r') as filepath: content = filepath.read() # Perform the replacement based on the index values @@ -68,12 +73,13 @@ def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: # Write the modified content back to the file with open(file, 'w') as filepath: filepath.write(replaced_content) - if(compile_generated_mutant(file)): + if(compile_generated_mutant(file, mappings)): if(run_test_cmd(command, file, timeout)): create_mutant_file(file, index, generator_name) - logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' in '{file}' ---> VALID\n")) + logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) return True reset_file(file) - logger.info(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' in '{file}' ---> INVALID\n")) + if verbose: + logger.info(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> INVALID\n")) return False \ No newline at end of file From 9db71678179c9b76546f91d0406cf52c40d970bc Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Tue, 16 Jan 2024 12:00:08 -0500 Subject: [PATCH 17/64] Updated run_test_cmd --- slither/tools/mutator/__main__.py | 1 + .../mutator/mutators/abstract_mutator.py | 2 +- .../mutator/utils/testing_generated_mutant.py | 23 ++----------------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index c41a82e35..8cbb103ad 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -165,6 +165,7 @@ def main() -> None: # mutation try: for compilation_unit_of_main_file in sl.compilation_units: + # TODO for M in _get_mutators(mutators_to_run): m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name, solc_remappings, verbose, output_folder) # check whether the contract instance exists or not diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index 5223e2d81..bd40ad6ac 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -97,7 +97,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- return self.contract_exist @abc.abstractmethod - def _mutate(self, test_cmd: str, test_dir: str) -> Dict: + def _mutate(self) -> Dict: """TODO Documentation""" return {} diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 6c6e80a55..65cf78c27 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -16,33 +16,14 @@ def compile_generated_mutant(file_path: str, mappings: str) -> bool: crytic_compile.CryticCompile(file_path, solc_remaps=mappings) return True except: # pylint: disable=broad-except - # logger.error("Error Crytic Compile") return False - -# function to run the tests -# def run_test_suite(cmd: str, dir: str) -> bool: -# try: -# # Change to the foundry folder -# # os.chdir(dir) - -# result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) -# # result = subprocess.run(cmd.split(' '), check=True) -# if not result.stderr: -# return True -# except subprocess.CalledProcessError as e: -# logger.error(f"Error executing '{cmd}': {e}") - -# return False -# except Exception as e: -# logger.error(f"An unexpected error occurred: {e}") -# return False def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: # add --fail-fast for foundry tests, to exit after first failure - if "forge test" in cmd and not "--fail-fast" in cmd : + if "forge test" in cmd and not "--fail-fast" in cmd: cmd += " --fail-fast" # add --bail for hardhat and truffle tests, to exit after first failure - elif not "--bail" in cmd: + elif "hardhat test" in cmd or "truffle test" and not "--bail" in cmd: cmd += " --bail" start = time.time() From 6ad193abd99198bde804144d21fc29fcc89feb86 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Wed, 17 Jan 2024 11:54:06 -0500 Subject: [PATCH 18/64] updated create patch --- slither/tools/mutator/__main__.py | 30 +++++++++++++++-- slither/tools/mutator/mutators/AOR.py | 4 +-- slither/tools/mutator/mutators/ASOR.py | 4 +-- slither/tools/mutator/mutators/BOR.py | 4 +-- slither/tools/mutator/mutators/CR.py | 32 +++++++++++++++++++ slither/tools/mutator/mutators/FHR.py | 4 +-- slither/tools/mutator/mutators/LIR.py | 6 ++-- slither/tools/mutator/mutators/LOR.py | 4 +-- slither/tools/mutator/mutators/MIA.py | 6 ++-- slither/tools/mutator/mutators/MVIE.py | 6 ++-- slither/tools/mutator/mutators/MVIV.py | 7 ++-- slither/tools/mutator/mutators/MWA.py | 4 +-- slither/tools/mutator/mutators/ROR.py | 4 +-- .../tools/mutator/mutators/{RCR.py => RR.py} | 14 +++----- slither/tools/mutator/mutators/SBR.py | 6 ++-- slither/tools/mutator/mutators/UOR.py | 10 +++--- .../tools/mutator/mutators/all_mutators.py | 5 ++- slither/tools/mutator/utils/file_handling.py | 2 +- slither/tools/mutator/utils/patch.py | 22 +++++++++++++ .../mutator/utils/testing_generated_mutant.py | 2 +- 20 files changed, 125 insertions(+), 51 deletions(-) create mode 100644 slither/tools/mutator/mutators/CR.py rename slither/tools/mutator/mutators/{RCR.py => RR.py} (66%) create mode 100644 slither/tools/mutator/utils/patch.py diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 8cbb103ad..66c0941a6 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -83,6 +83,20 @@ def parse_args() -> argparse.Namespace: help="mutant generators to run", ) + # list of contract names you want to mutate + parser.add_argument( + "--contract-names", + help="list of contract names you want to mutate", + ) + + # flag to run full mutation based revert mutator output + parser.add_argument( + "--quick", + help="to stop full mutation if revert mutator passes", + action="store_true", + default=False, + ) + # Initiate all the crytic config cli options cryticparser.init(parser) @@ -118,6 +132,7 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def main() -> None: args = parse_args() + # arguments test_command: str = args.test_cmd test_directory: str = args.test_dir @@ -127,6 +142,8 @@ def main() -> None: solc_remappings: str | None = args.solc_remaps verbose: bool = args.verbose mutators_to_run: List[str] | None = args.mutators_to_run + contract_names: List[str] | None = args.contract_names + quick_flag: bool = args.quick print(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) @@ -150,6 +167,13 @@ def main() -> None: if timeout == None: timeout = 30 + # setting RR mutator as first mutator + mutators_list = _get_mutators(mutators_to_run) + for M in mutators_list: + if M.NAME == "RR": + mutators_list.remove(M) + mutators_list.insert(0, M) + for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] # TODO: user provides contract name @@ -165,14 +189,16 @@ def main() -> None: # mutation try: for compilation_unit_of_main_file in sl.compilation_units: - # TODO - for M in _get_mutators(mutators_to_run): + for M in mutators_list: m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name, solc_remappings, verbose, output_folder) # check whether the contract instance exists or not if m.get_exist_flag(): count_valid, count_invalid = m.mutate() v_count += count_valid total_count += count_valid + count_invalid + if quick_flag: + if str(m.NAME) == 'RR' and v_count > 0: + break except Exception as e: logger.error(e) diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index 39e3a6a20..61eed67b1 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.unary_operation import UnaryOperation @@ -40,5 +40,5 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index 04ad8f8b0..e6fa41437 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -1,5 +1,5 @@ from typing import Dict -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation @@ -44,5 +44,5 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines # Replace the expression with true new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index de9ad287e..5ca46950f 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature bitwise_operators = [ @@ -33,5 +33,5 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/CR.py b/slither/tools/mutator/mutators/CR.py new file mode 100644 index 000000000..1935c43e6 --- /dev/null +++ b/slither/tools/mutator/mutators/CR.py @@ -0,0 +1,32 @@ +from typing import Dict +from slither.core.cfg.node import NodeType +from slither.tools.mutator.utils.patch import create_patch_with_line +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature + + +class CR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "CR" + HELP = 'Comment Replacement' + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + if node.type != NodeType.ENTRYPOINT and NodeType.ENDIF != node.type and NodeType.ENDLOOP != node.type: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + new_str = "//" + old_str + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + return result + + + + + + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index 5709346b1..3758306f3 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -1,5 +1,5 @@ from typing import Dict -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature import re @@ -31,6 +31,6 @@ class FHR(AbstractMutator): # pylint: disable=too-few-public-methods right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) != None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index 99228913a..c9966f1be 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -2,7 +2,7 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.core.solidity_types import ElementaryType literal_replacements = [] @@ -41,7 +41,7 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods old_value = old_str[old_str.find("=")+1:].strip() if old_value != value: new_str = f"{old_str.split('=')[0]}= {value}" - create_patch( + create_patch_with_line( result, self.in_file, start, @@ -69,7 +69,7 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods old_value = old_str[old_str.find("=")+1:].strip() if old_value != new_value: new_str = f"{old_str.split('=')[0]}= {new_value}" - create_patch( + create_patch_with_line( result, self.in_file, start, diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index fa66c7bca..e6903a01e 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature logical_operators = [ @@ -32,5 +32,5 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index f5bc52b16..0217324e0 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -1,6 +1,6 @@ from typing import Dict from slither.core.cfg.node import NodeType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation @@ -24,11 +24,11 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true and false for value in ["true", "false"]: new_str = value - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) print(node.expression) diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 3c334e9e6..c81182c43 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -2,7 +2,7 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" @@ -28,7 +28,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods new_str = old_str[: old_str.find("=")] line_no = variable.node_initialization.source_mapping.lines - create_patch( + create_patch_with_line( result, self.in_file, start, @@ -48,7 +48,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods new_str = old_str[: old_str.find("=")] line_no = variable.source_mapping.lines - create_patch( + create_patch_with_line( result, self.in_file, start, diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index 7f75b1dcf..890c55b1c 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -1,9 +1,8 @@ from typing import Dict - from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" @@ -28,7 +27,7 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] line_no = variable.node_initialization.source_mapping.lines - create_patch( + create_patch_with_line( result, self.in_file, start, @@ -46,7 +45,7 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] line_no = variable.source_mapping.lines - create_patch( + create_patch_with_line( result, self.in_file, start, diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index c6bacf485..9bb6a1600 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -1,6 +1,6 @@ from typing import Dict from slither.core.cfg.node import NodeType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation @@ -23,5 +23,5 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index e1c78c1eb..2a38ce323 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature relational_operators = [ @@ -36,6 +36,6 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/RCR.py b/slither/tools/mutator/mutators/RR.py similarity index 66% rename from slither/tools/mutator/mutators/RCR.py rename to slither/tools/mutator/mutators/RR.py index 96aebc68f..95cbf617a 100644 --- a/slither/tools/mutator/mutators/RCR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -1,12 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature -class RCR(AbstractMutator): # pylint: disable=too-few-public-methods - NAME = "RCR" - HELP = 'Revert and Comment Replacement' +class RR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "RR" + HELP = 'Revert Replacement' FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -22,11 +22,7 @@ class RCR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines if old_str != 'revert()': new_str = 'revert()' - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - new_str = "//" + old_str - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index 91c05b884..9e9afc1e5 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.core.cfg.node import NodeType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature import re from slither.core.variables.variable import Variable @@ -67,7 +67,7 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) != None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) for variable in self.contract.state_variables_declared: node = variable.node_initialization @@ -81,7 +81,7 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) != None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/UOR.py b/slither/tools/mutator/mutators/UOR.py index 671ee676d..aac4b02a6 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature unary_operators = [ @@ -36,16 +36,16 @@ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods variable_read = node.variables_read[0] new_str = str(variable_read) + str(op) if new_str != old_str and str(op) != '-': - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) new_str = str(op) + str(variable_read) - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) else: if node.expression.type != op: variable_read = node.variables_read[0] new_str = str(op) + str(variable_read) if new_str != old_str and str(op) != '-': - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) new_str = str(variable_read) + str(op) - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 9aa81a0fc..21925317d 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -12,6 +12,5 @@ from slither.tools.mutator.mutators.LIR import LIR # severity medium from slither.tools.mutator.mutators.FHR import FHR # severity medium from slither.tools.mutator.mutators.MIA import MIA # severity medium from slither.tools.mutator.mutators.ROR import ROR # severity medium -from slither.tools.mutator.mutators.RCR import RCR # severity high - - +from slither.tools.mutator.mutators.RR import RR # severity high +from slither.tools.mutator.mutators.CR import CR # severity high \ No newline at end of file diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index d61bba58a..01a142c8d 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -1,5 +1,5 @@ import os -from typing import Dict, Tuple, List +from typing import Dict, List import logging logger = logging.getLogger("Slither-Mutate") diff --git a/slither/tools/mutator/utils/patch.py b/slither/tools/mutator/utils/patch.py new file mode 100644 index 000000000..39c77f673 --- /dev/null +++ b/slither/tools/mutator/utils/patch.py @@ -0,0 +1,22 @@ +from typing import Dict, Union +from collections import defaultdict + +# pylint: disable=too-many-arguments +def create_patch_with_line( + result: Dict, + file: str, + start: int, + end: int, + old_str: Union[str, bytes], + new_str: Union[str, bytes], + line_no: int +) -> None: + if isinstance(old_str, bytes): + old_str = old_str.decode("utf8") + if isinstance(new_str, bytes): + new_str = new_str.decode("utf8") + p = {"start": start, "end": end, "old_string": old_str, "new_string": new_str, "line_number": line_no} + if "patches" not in result: + result["patches"] = defaultdict(list) + if p not in result["patches"][file]: + result["patches"][file].append(p) \ No newline at end of file diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 65cf78c27..8525e2808 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -4,7 +4,7 @@ import os import logging import time import signal -from typing import List, Dict +from typing import Dict from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_file from slither.utils.colors import green, red From 96e8adc39b9eb0cc12c13d51b0c32437444665dd Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Thu, 18 Jan 2024 10:49:42 -0500 Subject: [PATCH 19/64] Added contract_names arg --- slither/tools/mutator/__main__.py | 16 +++++++---- slither/tools/mutator/mutators/FHR.py | 2 -- .../mutator/mutators/abstract_mutator.py | 28 ++++--------------- .../mutator/utils/testing_generated_mutant.py | 4 ++- 4 files changed, 19 insertions(+), 31 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 66c0941a6..e576970f7 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -176,7 +176,6 @@ def main() -> None: for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] - # TODO: user provides contract name # slither object sl = Slither(filename, **vars(args)) # create a backup files @@ -189,10 +188,17 @@ def main() -> None: # mutation try: for compilation_unit_of_main_file in sl.compilation_units: - for M in mutators_list: - m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name, solc_remappings, verbose, output_folder) - # check whether the contract instance exists or not - if m.get_exist_flag(): + contract_instance = '' + for contract in compilation_unit_of_main_file.contracts: + if contract_names != None and contract.name in contract_names: + contract_instance = contract + elif str(contract.name).lower() == contract_name.lower(): + contract_instance = contract + if contract_instance == '': + logger.error("Can't find the contract") + else: + for M in mutators_list: + m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_instance, solc_remappings, verbose, output_folder) count_valid, count_invalid = m.mutate() v_count += count_valid total_count += count_valid + count_invalid diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index 3758306f3..a5d7f5f7f 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -3,8 +3,6 @@ from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature import re -# INFO: low severity - function_header_replacements = [ "pure ==> view", "view ==> pure", diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index bd40ad6ac..edd584386 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -7,6 +7,7 @@ from slither.core.compilation_unit import SlitherCompilationUnit from slither.formatters.utils.patches import apply_patch, create_diff from slither.tools.mutator.utils.testing_generated_mutant import test_patch from slither.utils.colors import yellow +from slither.core.declarations import Contract logger = logging.getLogger("Slither-Mutate") @@ -36,7 +37,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- timeout: int, testing_command: str, testing_directory: str, - contract_name: str, + contract_instance: Contract, solc_remappings: str | None, verbose: bool, output_folder: str, @@ -50,10 +51,12 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- self.test_command = testing_command self.test_directory = testing_directory self.timeout = timeout - self.contract_exist = False self.solc_remappings = solc_remappings self.verbose = verbose self.output_folder = output_folder + self.contract = contract_instance + self.in_file = self.contract.source_mapping.filename.absolute + self.in_file_str = self.contract.compilation_unit.core.source_code[self.in_file] if not self.NAME: raise IncorrectMutatorInitialization( @@ -74,27 +77,6 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- raise IncorrectMutatorInitialization( f"rate must be between 0 and 100 {self.__class__.__name__}" ) - - # identify the main contract, ignore the imports - for contract in self.slither.contracts: - # !limitation: what if the contract name is not same as file name - # !limitation: multi contract - if contract_name.lower() == str(contract.name).lower(): - # contract - self.contract = contract - # Retrieve the file - self.in_file = self.contract.source_mapping.filename.absolute - # Retrieve the source code - self.in_file_str = self.contract.compilation_unit.core.source_code[self.in_file] - # flag contract existence - self.contract_exist = True - - if not self.contract_exist: - self.contract_exist = False - logger.error(f"Contract name is not matching with the File name ({contract_name}). Please refer 'https://docs.soliditylang.org/en/latest/style-guide.html#contract-and-library-names')") - - def get_exist_flag(self) -> bool: - return self.contract_exist @abc.abstractmethod def _mutate(self) -> Dict: diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 8525e2808..2013858df 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -9,7 +9,7 @@ from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_ from slither.utils.colors import green, red logger = logging.getLogger("Slither-Mutate") - +# dont_mutate_line = {} # function to compile the generated mutant def compile_generated_mutant(file_path: str, mappings: str) -> bool: try: @@ -58,6 +58,8 @@ def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: if(run_test_cmd(command, file, timeout)): create_mutant_file(file, index, generator_name) logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) + # if generator_name == 'RR': + # dont_mutate_line[patch['line_number']] = True return True reset_file(file) From 48b6f6fee2bd82ae968d48b00eac23f97f4d46f2 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Sat, 20 Jan 2024 12:25:12 -0500 Subject: [PATCH 20/64] updated quick --- slither/tools/mutator/__main__.py | 22 +++++--- slither/tools/mutator/mutators/AOR.py | 8 +-- slither/tools/mutator/mutators/ASOR.py | 7 ++- slither/tools/mutator/mutators/BOR.py | 7 ++- slither/tools/mutator/mutators/CR.py | 5 +- slither/tools/mutator/mutators/FHR.py | 13 +++-- slither/tools/mutator/mutators/LIR.py | 55 ++++++++++--------- slither/tools/mutator/mutators/LOR.py | 8 +-- slither/tools/mutator/mutators/MIA.py | 20 +++---- slither/tools/mutator/mutators/MVIE.py | 40 +++++++------- slither/tools/mutator/mutators/MVIV.py | 38 +++++++------ slither/tools/mutator/mutators/MWA.py | 8 +-- slither/tools/mutator/mutators/ROR.py | 8 +-- slither/tools/mutator/mutators/RR.py | 7 ++- slither/tools/mutator/mutators/SBR.py | 28 +++++----- slither/tools/mutator/mutators/UOR.py | 35 ++++++------ .../mutator/mutators/abstract_mutator.py | 14 +++-- .../mutator/utils/testing_generated_mutant.py | 4 +- 18 files changed, 172 insertions(+), 155 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index e576970f7..80d025c97 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -169,10 +169,17 @@ def main() -> None: # setting RR mutator as first mutator mutators_list = _get_mutators(mutators_to_run) - for M in mutators_list: + + CR_RR_list = [] + duplicate_list = mutators_list.copy() + for M in duplicate_list: if M.NAME == "RR": mutators_list.remove(M) - mutators_list.insert(0, M) + CR_RR_list.insert(0,M) + elif M.NAME == "CR": + mutators_list.remove(M) + CR_RR_list.insert(1,M) + mutators_list = CR_RR_list + mutators_list for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] @@ -185,6 +192,7 @@ def main() -> None: # count of valid mutants v_count = 0 + dont_mutate_lines = [] # mutation try: for compilation_unit_of_main_file in sl.compilation_units: @@ -198,13 +206,13 @@ def main() -> None: logger.error("Can't find the contract") else: for M in mutators_list: - m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_instance, solc_remappings, verbose, output_folder) - count_valid, count_invalid = m.mutate() + m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_instance, solc_remappings, verbose, output_folder, dont_mutate_lines) + (count_valid, count_invalid, lines_list) = m.mutate() v_count += count_valid total_count += count_valid + count_invalid - if quick_flag: - if str(m.NAME) == 'RR' and v_count > 0: - break + dont_mutate_lines = lines_list + if not quick_flag: + dont_mutate_lines = [] except Exception as e: logger.error(e) diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index 61eed67b1..11593ee37 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -19,7 +19,6 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: try: @@ -38,7 +37,8 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index e6fa41437..29a6dc672 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -42,7 +42,8 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true + new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index 5ca46950f..6a5552a5f 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -31,7 +31,8 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/CR.py b/slither/tools/mutator/mutators/CR.py index 1935c43e6..79a63a88f 100644 --- a/slither/tools/mutator/mutators/CR.py +++ b/slither/tools/mutator/mutators/CR.py @@ -20,8 +20,9 @@ class CR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - new_str = "//" + old_str - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + new_str = "//" + old_str + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index a5d7f5f7f..84bfebe22 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -24,11 +24,12 @@ class FHR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + function.source_mapping.content.find('{') old_str = self.in_file_str[start:stop] line_no = function.source_mapping.lines - for value in function_header_replacements: - left_value = value.split(" ==> ")[0] - right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: - new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + for value in function_header_replacements: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index c9966f1be..e8217e935 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -36,20 +36,20 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + variable.source_mapping.length old_str = self.in_file_str[start:stop] line_no = variable.node_initialization.source_mapping.lines - # line_no = [0] - for value in literal_replacements: - old_value = old_str[old_str.find("=")+1:].strip() - if old_value != value: - new_str = f"{old_str.split('=')[0]}= {value}" - create_patch_with_line( - result, - self.in_file, - start, - stop, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + for value in literal_replacements: + old_value = old_str[old_str.find("=")+1:].strip() + if old_value != value: + new_str = f"{old_str.split('=')[0]}= {value}" + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0] + ) for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: @@ -65,18 +65,19 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + variable.source_mapping.length old_str = self.in_file_str[start:stop] line_no = variable.source_mapping.lines - for new_value in literal_replacements: - old_value = old_str[old_str.find("=")+1:].strip() - if old_value != new_value: - new_str = f"{old_str.split('=')[0]}= {new_value}" - create_patch_with_line( - result, - self.in_file, - start, - stop, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + for new_value in literal_replacements: + old_value = old_str[old_str.find("=")+1:].strip() + if old_value != new_value: + new_str = f"{old_str.split('=')[0]}= {new_value}" + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0] + ) return result diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index e6903a01e..e14c85708 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -29,8 +29,8 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 0217324e0..421f94a5e 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -20,16 +20,14 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.expression.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true and false + for value in ["true", "false"]: + new_str = value + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + if not isinstance(node.expression, UnaryOperation): + new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - # Replace the expression with true and false - for value in ["true", "false"]: - new_str = value - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - if not isinstance(node.expression, UnaryOperation): - new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - print(node.expression) - return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index c81182c43..4ae387d29 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -25,18 +25,18 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods start = variable.source_mapping.start stop = variable.expression.source_mapping.start old_str = self.in_file_str[start:stop] - new_str = old_str[: old_str.find("=")] line_no = variable.node_initialization.source_mapping.lines - create_patch_with_line( - result, - self.in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + create_patch_with_line( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no[0] + ) for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: @@ -45,17 +45,17 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods start = variable.source_mapping.start stop = variable.expression.source_mapping.start old_str = self.in_file_str[start:stop] - new_str = old_str[: old_str.find("=")] line_no = variable.source_mapping.lines - create_patch_with_line( - result, - self.in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + create_patch_with_line( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no[0] + ) return result diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index 890c55b1c..68bc2f2d8 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -27,15 +27,16 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] line_no = variable.node_initialization.source_mapping.lines - create_patch_with_line( - result, - self.in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + create_patch_with_line( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no[0] + ) for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: @@ -45,14 +46,15 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] line_no = variable.source_mapping.lines - create_patch_with_line( - result, - self.in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + create_patch_with_line( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no[0] + ) return result diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index 9bb6a1600..4c1e91b32 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -20,8 +20,8 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - - if not isinstance(node.expression, UnaryOperation): - new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + if not isinstance(node.expression, UnaryOperation): + new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index 2a38ce323..da75a592a 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -33,9 +33,9 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + ir.expression.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/RR.py b/slither/tools/mutator/mutators/RR.py index 95cbf617a..3aab255ec 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -20,9 +20,10 @@ class RR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - if old_str != 'revert()': - new_str = 'revert()' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + if old_str != 'revert()': + new_str = 'revert()' + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index 9e9afc1e5..f6adfff84 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -56,18 +56,19 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if node.type != NodeType.ENTRYPOINT: + if node.type != NodeType.ENTRYPOINT and node.type != NodeType.ENDIF and node.type != NodeType.ENDLOOP: # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - for value in solidity_rules: - left_value = value.split(" ==> ")[0] - right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: - new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + for value in solidity_rules: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) for variable in self.contract.state_variables_declared: node = variable.node_initialization @@ -76,12 +77,13 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - for value in solidity_rules: - left_value = value.split(" ==> ")[0] - right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: - new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + for value in solidity_rules: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/UOR.py b/slither/tools/mutator/mutators/UOR.py index aac4b02a6..fa00b52ae 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -29,23 +29,24 @@ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - if isinstance(ir_expression, UnaryOperation) and ir_expression.type in unary_operators: - for op in unary_operators: - if not node.expression.is_prefix: - if node.expression.type != op: - variable_read = node.variables_read[0] - new_str = str(variable_read) + str(op) - if new_str != old_str and str(op) != '-': + if not line_no[0] in self.dont_mutate_line: + if isinstance(ir_expression, UnaryOperation) and ir_expression.type in unary_operators: + for op in unary_operators: + if not node.expression.is_prefix: + if node.expression.type != op: + variable_read = node.variables_read[0] + new_str = str(variable_read) + str(op) + if new_str != old_str and str(op) != '-': + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(op) + str(variable_read) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - new_str = str(op) + str(variable_read) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - else: - if node.expression.type != op: - variable_read = node.variables_read[0] - new_str = str(op) + str(variable_read) - if new_str != old_str and str(op) != '-': + else: + if node.expression.type != op: + variable_read = node.variables_read[0] + new_str = str(op) + str(variable_read) + if new_str != old_str and str(op) != '-': + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(variable_read) + str(op) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - new_str = str(variable_read) + str(op) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index edd584386..f11d69db1 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -1,7 +1,7 @@ import abc import logging from enum import Enum -from typing import Optional, Dict, Tuple +from typing import Optional, Dict, Tuple, List from slither.core.compilation_unit import SlitherCompilationUnit # from slither.tools.doctor.utils import snip_section from slither.formatters.utils.patches import apply_patch, create_diff @@ -41,6 +41,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- solc_remappings: str | None, verbose: bool, output_folder: str, + dont_mutate_line: List[int], rate: int = 10, seed: Optional[int] = None ) -> None: @@ -57,6 +58,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- self.contract = contract_instance self.in_file = self.contract.source_mapping.filename.absolute self.in_file_str = self.contract.compilation_unit.core.source_code[self.in_file] + self.dont_mutate_line = dont_mutate_line if not self.NAME: raise IncorrectMutatorInitialization( @@ -83,13 +85,12 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- """TODO Documentation""" return {} - def mutate(self) -> Tuple[int, int]: + def mutate(self) -> Tuple[int, int, List[int]]: # call _mutate function from different mutators (all_patches) = self._mutate() - if "patches" not in all_patches: logger.debug(f"No patches found by {self.NAME}") - return (0,0) + return (0,0,self.dont_mutate_line) for file in all_patches["patches"]: original_txt = self.slither.source_code[file].encode("utf8") @@ -99,6 +100,8 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- for patch in patches: # test the patch flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout, self.solc_remappings, self.verbose) + if (self.NAME == 'RR' or self.NAME == 'CR') and flag: + self.dont_mutate_line.append(patch['line_number']) # count the valid and invalid mutants if not flag: self.INVALID_MUTANTS_COUNT += 1 @@ -112,8 +115,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # add valid mutant patches to a output file with open(self.output_folder + "/patches_file.txt", 'a') as patches_file: patches_file.write(diff + '\n') - - return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) + return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 2013858df..8525e2808 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -9,7 +9,7 @@ from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_ from slither.utils.colors import green, red logger = logging.getLogger("Slither-Mutate") -# dont_mutate_line = {} + # function to compile the generated mutant def compile_generated_mutant(file_path: str, mappings: str) -> bool: try: @@ -58,8 +58,6 @@ def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: if(run_test_cmd(command, file, timeout)): create_mutant_file(file, index, generator_name) logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) - # if generator_name == 'RR': - # dont_mutate_line[patch['line_number']] = True return True reset_file(file) From 799117d0868a0e2eaab0085b42eb416822942328 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Sun, 21 Jan 2024 12:08:13 -0500 Subject: [PATCH 21/64] Added README --- slither/tools/mutator/README.md | 31 +++++++++++++++++++ slither/tools/mutator/__main__.py | 12 ++++--- .../mutator/mutators/abstract_mutator.py | 2 +- slither/tools/mutator/utils/file_handling.py | 4 +-- 4 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 slither/tools/mutator/README.md diff --git a/slither/tools/mutator/README.md b/slither/tools/mutator/README.md new file mode 100644 index 000000000..11b0b7eb5 --- /dev/null +++ b/slither/tools/mutator/README.md @@ -0,0 +1,31 @@ +# Slither-mutate + +`slither-mutate` is a mutation testing tool for solidity based smart contracts. + +## Usage + +`slither-mutate ` + +### CLI Interface + +``` +positional arguments: + codebase Codebase to analyze (.sol file, truffle directory, ...) + test-cmd Command to run the tests for your project + +options: + -h, --help show this help message and exit + --list-mutators List available detectors + --test-dir TEST_DIR Tests directory + --ignore-dirs IGNORE_DIRS + Directories to ignore + --timeout TIMEOUT Set timeout for test command (by default 30 seconds) + --output-dir OUTPUT_DIR + Name of output Directory (by default 'mutation_campaign') + --verbose output all mutants generated + --mutators-to-run MUTATORS_TO_RUN + mutant generators to run + --contract-names CONTRACT_NAMES + list of contract names you want to mutate + --quick to stop full mutation if revert mutator passes +``` \ No newline at end of file diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 80d025c97..b375e9558 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -41,14 +41,14 @@ def parse_args() -> argparse.Namespace: # argument to add the test command parser.add_argument( - "--test-cmd", - help="Command line needed to run the tests for your project" + "test-cmd", + help="Command to run the tests for your project" ) # argument to add the test directory - containing all the tests parser.add_argument( "--test-dir", - help="Directory of tests" + help="Tests directory" ) # argument to ignore the interfaces, libraries @@ -66,7 +66,7 @@ def parse_args() -> argparse.Namespace: # output directory argument parser.add_argument( "--output-dir", - help="Output Directory (by default 'mutation_campaign')" + help="Name of output directory (by default 'mutation_campaign')" ) # to print just all the mutants @@ -170,6 +170,7 @@ def main() -> None: # setting RR mutator as first mutator mutators_list = _get_mutators(mutators_to_run) + # insert RR and CR in front of the list CR_RR_list = [] duplicate_list = mutators_list.copy() for M in duplicate_list: @@ -191,8 +192,9 @@ def main() -> None: total_count = 0 # count of valid mutants v_count = 0 - + # lines those need not be mutated (taken from RR and CR) dont_mutate_lines = [] + # mutation try: for compilation_unit_of_main_file in sl.compilation_units: diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index f11d69db1..558a51451 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -3,7 +3,6 @@ import logging from enum import Enum from typing import Optional, Dict, Tuple, List from slither.core.compilation_unit import SlitherCompilationUnit -# from slither.tools.doctor.utils import snip_section from slither.formatters.utils.patches import apply_patch, create_diff from slither.tools.mutator.utils.testing_generated_mutant import test_patch from slither.utils.colors import yellow @@ -100,6 +99,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- for patch in patches: # test the patch flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout, self.solc_remappings, self.verbose) + # if RR or CR and valid mutant, add line no. if (self.NAME == 'RR' or self.NAME == 'CR') and flag: self.dont_mutate_line.append(patch['line_number']) # count the valid and invalid mutants diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index 01a142c8d..ffebee9fc 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -104,6 +104,4 @@ def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str for i in get_sol_file_list(filename, ignore_paths): sol_file_list.append(i) - return sol_file_list - -# TODO: create a function to delete the commands from the sol file + return sol_file_list \ No newline at end of file From 5fb5f69b8e15480eeb0cd37b22f8123719ebe7e3 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Wed, 24 Jan 2024 11:47:55 -0500 Subject: [PATCH 22/64] Updated arguments --- slither/tools/mutator/README.md | 6 +++--- slither/tools/mutator/__main__.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/slither/tools/mutator/README.md b/slither/tools/mutator/README.md index 11b0b7eb5..c615b0b79 100644 --- a/slither/tools/mutator/README.md +++ b/slither/tools/mutator/README.md @@ -4,24 +4,24 @@ ## Usage -`slither-mutate ` +`slither-mutate --test-cmd ` ### CLI Interface ``` positional arguments: codebase Codebase to analyze (.sol file, truffle directory, ...) - test-cmd Command to run the tests for your project options: -h, --help show this help message and exit --list-mutators List available detectors + --test-cmd TEST_CMD Command to run the tests for your project --test-dir TEST_DIR Tests directory --ignore-dirs IGNORE_DIRS Directories to ignore --timeout TIMEOUT Set timeout for test command (by default 30 seconds) --output-dir OUTPUT_DIR - Name of output Directory (by default 'mutation_campaign') + Name of output directory (by default 'mutation_campaign') --verbose output all mutants generated --mutators-to-run MUTATORS_TO_RUN mutant generators to run diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index b375e9558..7bd4f8d79 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -26,7 +26,7 @@ logger.setLevel(logging.INFO) def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Experimental smart contract mutator. Based on https://arxiv.org/abs/2006.11597", - usage="slither-mutate target", + usage="slither-mutate --test-cmd ", ) parser.add_argument("codebase", help="Codebase to analyze (.sol file, truffle directory, ...)") @@ -41,7 +41,7 @@ def parse_args() -> argparse.Namespace: # argument to add the test command parser.add_argument( - "test-cmd", + "--test-cmd", help="Command to run the tests for your project" ) From 71f970f0517befa56ae6875f6c7d7711789024dd Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Wed, 24 Jan 2024 14:49:28 -0500 Subject: [PATCH 23/64] Updated mutators --- slither/tools/mutator/README.md | 2 ++ slither/tools/mutator/__main__.py | 2 +- slither/tools/mutator/mutators/AOR.py | 3 +-- slither/tools/mutator/mutators/ASOR.py | 3 +-- slither/tools/mutator/mutators/BOR.py | 3 +-- slither/tools/mutator/mutators/CR.py | 3 +-- slither/tools/mutator/mutators/FHR.py | 3 +-- slither/tools/mutator/mutators/LIR.py | 3 +-- slither/tools/mutator/mutators/LOR.py | 3 +-- slither/tools/mutator/mutators/MIA.py | 3 +-- slither/tools/mutator/mutators/MVIE.py | 3 +-- slither/tools/mutator/mutators/MVIV.py | 3 +-- slither/tools/mutator/mutators/MWA.py | 3 +-- slither/tools/mutator/mutators/ROR.py | 3 +-- slither/tools/mutator/mutators/RR.py | 4 +--- slither/tools/mutator/mutators/SBR.py | 3 +-- slither/tools/mutator/mutators/UOR.py | 3 +-- .../mutator/mutators/abstract_mutator.py | 24 +------------------ slither/tools/mutator/utils/command_line.py | 13 +++++----- 19 files changed, 25 insertions(+), 62 deletions(-) diff --git a/slither/tools/mutator/README.md b/slither/tools/mutator/README.md index c615b0b79..30b83ac46 100644 --- a/slither/tools/mutator/README.md +++ b/slither/tools/mutator/README.md @@ -6,6 +6,8 @@ `slither-mutate --test-cmd ` +To view the list of mutators available `slither-mutate --list-mutators` + ### CLI Interface ``` diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 7bd4f8d79..13e78a30e 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -118,7 +118,7 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def __call__( self, parser: Any, *args: Any, **kwargs: Any ) -> None: # pylint: disable=signature-differs - checks = _get_mutators() + checks = _get_mutators(None) output_mutators(checks) parser.exit() diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index 11593ee37..0c7f906b3 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.unary_operation import UnaryOperation arithmetic_operators = [ @@ -15,7 +15,6 @@ arithmetic_operators = [ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "AOR" HELP = "Arithmetic operator replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index 29a6dc672..551cf8c64 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation assignment_operators = [ @@ -20,7 +20,6 @@ assignment_operators = [ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ASOR" HELP = "Assignment Operator Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index 6a5552a5f..b6a9ae749 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator bitwise_operators = [ BinaryType.AND, @@ -14,7 +14,6 @@ bitwise_operators = [ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "BOR" HELP = "Bitwise Operator Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/CR.py b/slither/tools/mutator/mutators/CR.py index 79a63a88f..5c34416e9 100644 --- a/slither/tools/mutator/mutators/CR.py +++ b/slither/tools/mutator/mutators/CR.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator class CR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "CR" HELP = 'Comment Replacement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index 84bfebe22..847466611 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator import re function_header_replacements = [ @@ -13,7 +13,6 @@ function_header_replacements = [ class FHR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "FHR" HELP = 'Function Header Replacement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index e8217e935..29efe6502 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.tools.mutator.utils.patch import create_patch_with_line from slither.core.solidity_types import ElementaryType @@ -10,7 +10,6 @@ literal_replacements = [] class LIR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LIR" HELP = "Literal Interger Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index e14c85708..a8fff1c31 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator logical_operators = [ BinaryType.OROR, @@ -11,7 +11,6 @@ logical_operators = [ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LOR" HELP = "Logical Operator Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 421f94a5e..592014349 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" HELP = '"if" construct around statement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 4ae387d29..b562ba9b0 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.tools.mutator.utils.patch import create_patch_with_line class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" HELP = "variable initialization using an expression" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index 68bc2f2d8..dcb5be259 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.tools.mutator.utils.patch import create_patch_with_line class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" HELP = "variable initialization using a value" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index 4c1e91b32..b482ab566 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation class MWA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MWA" HELP = '"while" construct around statement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index da75a592a..826b15a4a 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator relational_operators = [ BinaryType.LESS, @@ -15,7 +15,6 @@ relational_operators = [ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ROR" HELP = "Relational Operator Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/RR.py b/slither/tools/mutator/mutators/RR.py index 3aab255ec..5afe18892 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -1,13 +1,11 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature - +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator class RR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "RR" HELP = 'Revert Replacement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index f6adfff84..0e9432908 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator import re from slither.core.variables.variable import Variable @@ -47,7 +47,6 @@ solidity_rules = [ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "SBR" HELP = 'Solidity Based Replacement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: diff --git a/slither/tools/mutator/mutators/UOR.py b/slither/tools/mutator/mutators/UOR.py index fa00b52ae..cf62c21bd 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator unary_operators = [ UnaryOperationType.PLUSPLUS_PRE, @@ -14,7 +14,6 @@ unary_operators = [ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "UOR" HELP = "Unary Operator Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index 558a51451..ea331e7c5 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -1,6 +1,5 @@ import abc import logging -from enum import Enum from typing import Optional, Dict, Tuple, List from slither.core.compilation_unit import SlitherCompilationUnit from slither.formatters.utils.patches import apply_patch, create_diff @@ -12,22 +11,10 @@ logger = logging.getLogger("Slither-Mutate") class IncorrectMutatorInitialization(Exception): pass - -class FaultNature(Enum): - Missing = 0 - Wrong = 1 - Extraneous = 2 - Undefined = 100 - - # not executed - can be detected by replacing with revert - # has no effect - can be detected by removing a line / comment - # can have valid mutant - # can't have valid mutant class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public-methods NAME = "" HELP = "" - FAULTNATURE = FaultNature.Undefined VALID_MUTANTS_COUNT = 0 INVALID_MUTANTS_COUNT = 0 @@ -69,11 +56,6 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- f"HELP is not initialized {self.__class__.__name__}" ) - if self.FAULTNATURE == FaultNature.Undefined: - raise IncorrectMutatorInitialization( - f"FAULTNATURE is not initialized {self.__class__.__name__}" - ) - if rate < 0 or rate > 100: raise IncorrectMutatorInitialization( f"rate must be between 0 and 100 {self.__class__.__name__}" @@ -115,8 +97,4 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # add valid mutant patches to a output file with open(self.output_folder + "/patches_file.txt", 'a') as patches_file: patches_file.write(diff + '\n') - return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) - - - - \ No newline at end of file + return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) \ No newline at end of file diff --git a/slither/tools/mutator/utils/command_line.py b/slither/tools/mutator/utils/command_line.py index 042b4fff7..358586688 100644 --- a/slither/tools/mutator/utils/command_line.py +++ b/slither/tools/mutator/utils/command_line.py @@ -7,14 +7,13 @@ def output_mutators(mutators_classes: List[Type[AbstractMutator]]) -> None: for detector in mutators_classes: argument = detector.NAME help_info = detector.HELP - fault_nature = detector.FAULTNATURE.name - mutators_list.append((argument, help_info, fault_nature)) - table = MyPrettyTable(["Num", "Name", "What it Does", "Fault Nature"]) + mutators_list.append((argument, help_info)) + table = MyPrettyTable(["Num", "Name", "What it Does"]) - # Sort by class, nature, name - mutators_list = sorted(mutators_list, key=lambda element: (element[2], element[0])) + # Sort by class + mutators_list = sorted(mutators_list, key=lambda element: (element[0])) idx = 1 - for (argument, help_info, fault_nature) in mutators_list: - table.add_row([str(idx), argument, help_info, fault_nature]) + for (argument, help_info) in mutators_list: + table.add_row([str(idx), argument, help_info]) idx = idx + 1 print(table) From c8462b24339a36b3c9faa48524fe184d1ce844dc Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Thu, 25 Jan 2024 12:46:34 -0500 Subject: [PATCH 24/64] Updated files --- slither/tools/mutator/README.md | 8 +-- slither/tools/mutator/__main__.py | 66 ++++++++++--------- slither/tools/mutator/mutators/AOR.py | 6 +- slither/tools/mutator/mutators/ASOR.py | 6 +- slither/tools/mutator/mutators/BOR.py | 4 +- slither/tools/mutator/mutators/CR.py | 13 +--- slither/tools/mutator/mutators/FHR.py | 13 ++-- slither/tools/mutator/mutators/LIR.py | 7 +- slither/tools/mutator/mutators/LOR.py | 4 +- slither/tools/mutator/mutators/MIA.py | 7 +- slither/tools/mutator/mutators/MVIE.py | 3 +- slither/tools/mutator/mutators/MVIV.py | 3 +- slither/tools/mutator/mutators/MWA.py | 7 +- slither/tools/mutator/mutators/ROR.py | 3 +- slither/tools/mutator/mutators/RR.py | 10 +-- slither/tools/mutator/mutators/SBR.py | 20 ++---- slither/tools/mutator/mutators/UOR.py | 7 +- .../mutator/mutators/abstract_mutator.py | 30 ++++----- .../tools/mutator/mutators/all_mutators.py | 4 +- slither/tools/mutator/utils/file_handling.py | 60 +++++++++-------- slither/tools/mutator/utils/patch.py | 2 +- .../mutator/utils/testing_generated_mutant.py | 54 ++++++++++----- 22 files changed, 168 insertions(+), 169 deletions(-) diff --git a/slither/tools/mutator/README.md b/slither/tools/mutator/README.md index 30b83ac46..8af977b08 100644 --- a/slither/tools/mutator/README.md +++ b/slither/tools/mutator/README.md @@ -1,6 +1,6 @@ # Slither-mutate -`slither-mutate` is a mutation testing tool for solidity based smart contracts. +`slither-mutate` is a mutation testing tool for solidity based smart contracts. ## Usage @@ -10,9 +10,9 @@ To view the list of mutators available `slither-mutate --list-mutators` ### CLI Interface -``` +```shell positional arguments: - codebase Codebase to analyze (.sol file, truffle directory, ...) + codebase Codebase to analyze (.sol file, project directory, ...) options: -h, --help show this help message and exit @@ -30,4 +30,4 @@ options: --contract-names CONTRACT_NAMES list of contract names you want to mutate --quick to stop full mutation if revert mutator passes -``` \ No newline at end of file +``` diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 13e78a30e..56582d6f5 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -4,14 +4,14 @@ import logging import sys import os import shutil -from typing import Type, List, Any +from typing import Type, List, Any, Optional from crytic_compile import cryticparser from slither import Slither from slither.tools.mutator.mutators import all_mutators +from slither.utils.colors import yellow, magenta from .mutators.abstract_mutator import AbstractMutator from .utils.command_line import output_mutators from .utils.file_handling import transfer_and_delete, backup_source_file, get_sol_file_list -from slither.utils.colors import yellow, magenta logging.basicConfig() logger = logging.getLogger("Slither-Mutate") @@ -24,12 +24,16 @@ logger.setLevel(logging.INFO) ################################################################################### def parse_args() -> argparse.Namespace: + """ + Parse the underlying arguments for the program. + Returns: The arguments for the program. + """ parser = argparse.ArgumentParser( description="Experimental smart contract mutator. Based on https://arxiv.org/abs/2006.11597", usage="slither-mutate --test-cmd ", ) - parser.add_argument("codebase", help="Codebase to analyze (.sol file, truffle directory, ...)") + parser.add_argument("codebase", help="Codebase to analyze (.sol file, project directory, ...)") parser.add_argument( "--list-mutators", @@ -108,7 +112,7 @@ def parse_args() -> argparse.Namespace: def _get_mutators(mutators_list: List[str] | None) -> List[Type[AbstractMutator]]: detectors_ = [getattr(all_mutators, name) for name in dir(all_mutators)] - if not mutators_list is None: + if mutators_list is not None: detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) and str(c.NAME) in mutators_list ] else: detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) ] @@ -122,7 +126,6 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods output_mutators(checks) parser.exit() - # endregion ################################################################################### ################################################################################### @@ -130,46 +133,46 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods ################################################################################### ################################################################################### -def main() -> None: +def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too-many-locals args = parse_args() # arguments test_command: str = args.test_cmd - test_directory: str = args.test_dir - paths_to_ignore: str | None = args.ignore_dirs - output_dir: str | None = args.output_dir - timeout: int | None = args.timeout - solc_remappings: str | None = args.solc_remaps - verbose: bool = args.verbose - mutators_to_run: List[str] | None = args.mutators_to_run - contract_names: List[str] | None = args.contract_names - quick_flag: bool = args.quick - - print(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) + test_directory: Optional[str] = args.test_dir + paths_to_ignore: Optional[str] = args.ignore_dirs + output_dir: Optional[str] = args.output_dir + timeout: Optional[int] = args.timeout + solc_remappings: Optional[str] = args.solc_remaps + verbose: Optional[bool] = args.verbose + mutators_to_run: Optional[List[str]] = args.mutators_to_run + contract_names: Optional[List[str]] = args.contract_names + quick_flag: Optional[bool] = args.quick + + logger.info(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) if paths_to_ignore: paths_to_ignore_list = paths_to_ignore.strip('][').split(',') - print(magenta(f"Ignored paths - {', '.join(paths_to_ignore_list)} \n")) + logger.info(magenta(f"Ignored paths - {', '.join(paths_to_ignore_list)} \n")) else: paths_to_ignore_list = [] - # get all the contracts as a list from given codebase + # get all the contracts as a list from given codebase sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore_list) # folder where backup files and valid mutants created - if output_dir == None: + if output_dir is None: output_dir = "/mutation_campaign" output_folder = os.getcwd() + output_dir if os.path.exists(output_folder): shutil.rmtree(output_folder) # set default timeout - if timeout == None: + if timeout is None: timeout = 30 # setting RR mutator as first mutator mutators_list = _get_mutators(mutators_to_run) - + # insert RR and CR in front of the list CR_RR_list = [] duplicate_list = mutators_list.copy() @@ -178,15 +181,15 @@ def main() -> None: mutators_list.remove(M) CR_RR_list.insert(0,M) elif M.NAME == "CR": - mutators_list.remove(M) + mutators_list.remove(M) CR_RR_list.insert(1,M) mutators_list = CR_RR_list + mutators_list - for filename in sol_file_list: + for filename in sol_file_list: # pylint: disable=too-many-nested-blocks contract_name = os.path.split(filename)[1].split('.sol')[0] # slither object sl = Slither(filename, **vars(args)) - # create a backup files + # create a backup files files_dict = backup_source_file(sl.source_code, output_folder) # total count of mutants total_count = 0 @@ -200,7 +203,7 @@ def main() -> None: for compilation_unit_of_main_file in sl.compilation_units: contract_instance = '' for contract in compilation_unit_of_main_file.contracts: - if contract_names != None and contract.name in contract_names: + if contract_names is not None and contract.name in contract_names: contract_instance = contract elif str(contract.name).lower() == contract_name.lower(): contract_instance = contract @@ -215,20 +218,19 @@ def main() -> None: dont_mutate_lines = lines_list if not quick_flag: dont_mutate_lines = [] - except Exception as e: + except Exception as e: # pylint: disable=broad-except logger.error(e) except KeyboardInterrupt: # transfer and delete the backup files if interrupted logger.error("\nExecution interrupted by user (Ctrl + C). Cleaning up...") transfer_and_delete(files_dict) - + # transfer and delete the backup files transfer_and_delete(files_dict) - + # output - print(yellow(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n")) + logger.info(yellow(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n")) - print(magenta(f"Finished Mutation Campaign in '{args.codebase}' \n")) + logger.info(magenta(f"Finished Mutation Campaign in '{args.codebase}' \n")) # endregion - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index 0c7f906b3..00506a1bb 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -18,11 +18,11 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: try: ir_expression = node.expression - except: + except: # pylint: disable=bare-except continue for ir in node.irs: if isinstance(ir, Binary) and ir.type in arithmetic_operators: @@ -40,4 +40,4 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index 551cf8c64..0e7452594 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -24,7 +24,7 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: for ir in node.irs: if isinstance(ir.expression, AssignmentOperation) and ir.expression.type in assignment_operators: @@ -33,7 +33,7 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods alternative_ops = assignment_operators[:] try: alternative_ops.remove(ir.expression.type) - except: + except: # pylint: disable=bare-except continue for op in alternative_ops: if op != ir.expression: @@ -45,4 +45,4 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index b6a9ae749..9f8ca2a11 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -18,7 +18,7 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in bitwise_operators: @@ -34,4 +34,4 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/CR.py b/slither/tools/mutator/mutators/CR.py index 5c34416e9..296028236 100644 --- a/slither/tools/mutator/mutators/CR.py +++ b/slither/tools/mutator/mutators/CR.py @@ -11,22 +11,15 @@ class CR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: - if node.type != NodeType.ENTRYPOINT and NodeType.ENDIF != node.type and NodeType.ENDLOOP != node.type: + if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = self.in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: new_str = "//" + old_str create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result - - - - - - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index 847466611..4560db4da 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -1,7 +1,8 @@ from typing import Dict +import re from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator -import re + function_header_replacements = [ "pure ==> view", @@ -16,9 +17,8 @@ class FHR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - - for function in self.contract.functions_and_modifiers_declared: - # function_header = function.source_mapping.content.split('{')[0] + + for function in self.contract.functions_and_modifiers_declared: start = function.source_mapping.start stop = start + function.source_mapping.content.find('{') old_str = self.in_file_str[start:stop] @@ -27,8 +27,7 @@ class FHR(AbstractMutator): # pylint: disable=too-few-public-methods for value in function_header_replacements: left_value = value.split(" ==> ")[0] right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: + if re.search(re.compile(left_value), old_str) is not None: new_str = re.sub(re.compile(left_value), right_value, old_str) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index 29efe6502..f9ef874cd 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -11,12 +11,12 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LIR" HELP = "Literal Interger Replacement" - def _mutate(self) -> Dict: + def _mutate(self) -> Dict: # pylint: disable=too-many-branches result: Dict = {} variable: Variable # Create fault for state variables declaration - for variable in self.contract.state_variables_declared: + for variable in self.contract.state_variables_declared: # pylint: disable=too-many-nested-blocks if variable.initialized: # Cannot remove the initialization of constant variables if variable.is_constant: @@ -50,7 +50,7 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods line_no[0] ) - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for variable in function.local_variables: if variable.initialized and isinstance(variable.expression, Literal): if isinstance(variable.type, ElementaryType): @@ -78,5 +78,4 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods new_str, line_no[0] ) - return result diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index a8fff1c31..21837d81e 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -15,7 +15,7 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in logical_operators: @@ -32,4 +32,4 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 592014349..a10ce1f1d 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -10,7 +10,6 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: if node.type == NodeType.IF: @@ -24,9 +23,9 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods for value in ["true", "false"]: new_str = value create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - + if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - return result \ No newline at end of file + return result + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index b562ba9b0..678b3b747 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -56,5 +56,4 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods new_str, line_no[0] ) - - return result + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index dcb5be259..c82f132d7 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -55,5 +55,4 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods new_str, line_no[0] ) - - return result + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index b482ab566..20447290a 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -10,7 +10,7 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: if node.type == NodeType.IFLOOP: @@ -22,5 +22,6 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result \ No newline at end of file + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index 826b15a4a..d59e7575a 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -19,7 +19,7 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in relational_operators: @@ -37,4 +37,3 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result - diff --git a/slither/tools/mutator/mutators/RR.py b/slither/tools/mutator/mutators/RR.py index 5afe18892..6bfd644e0 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -12,20 +12,14 @@ class RR(AbstractMutator): # pylint: disable=too-few-public-methods for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if node.type != NodeType.ENTRYPOINT and NodeType.ENDIF != node.type and NodeType.ENDLOOP != node.type: + if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = self.in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: if old_str != 'revert()': new_str = 'revert()' create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result - - - - - - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index 0e9432908..bbdc63194 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -1,8 +1,8 @@ from typing import Dict +import re from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator -import re from slither.core.variables.variable import Variable solidity_rules = [ @@ -43,19 +43,17 @@ solidity_rules = [ "while ==> if", ] - class SBR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "SBR" HELP = 'Solidity Based Replacement' def _mutate(self) -> Dict: - result: Dict = {} variable: Variable - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: - if node.type != NodeType.ENTRYPOINT and node.type != NodeType.ENDIF and node.type != NodeType.ENDLOOP: + if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length @@ -65,11 +63,11 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods for value in solidity_rules: left_value = value.split(" ==> ")[0] right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: + if re.search(re.compile(left_value), old_str) is not None: new_str = re.sub(re.compile(left_value), right_value, old_str) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - for variable in self.contract.state_variables_declared: + for variable in self.contract.state_variables_declared: # pylint: disable=too-many-nested-blocks node = variable.node_initialization if node: start = node.source_mapping.start @@ -80,13 +78,7 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods for value in solidity_rules: left_value = value.split(" ==> ")[0] right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: + if re.search(re.compile(left_value), old_str) is not None: new_str = re.sub(re.compile(left_value), right_value, old_str) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result - - - - - - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/UOR.py b/slither/tools/mutator/mutators/UOR.py index cf62c21bd..b7e8c8156 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -18,11 +18,11 @@ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: try: ir_expression = node.expression - except: + except: # pylint: disable=bare-except continue start = node.source_mapping.start stop = start + node.source_mapping.length @@ -47,5 +47,4 @@ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) new_str = str(variable_read) + str(op) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index ea331e7c5..c2f15cd74 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -11,24 +11,24 @@ logger = logging.getLogger("Slither-Mutate") class IncorrectMutatorInitialization(Exception): pass - + class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public-methods NAME = "" HELP = "" VALID_MUTANTS_COUNT = 0 INVALID_MUTANTS_COUNT = 0 - def __init__( - self, compilation_unit: SlitherCompilationUnit, - timeout: int, - testing_command: str, - testing_directory: str, - contract_instance: Contract, - solc_remappings: str | None, + def __init__( # pylint: disable=too-many-arguments + self, compilation_unit: SlitherCompilationUnit, + timeout: int, + testing_command: str, + testing_directory: str, + contract_instance: Contract, + solc_remappings: str | None, verbose: bool, output_folder: str, dont_mutate_line: List[int], - rate: int = 10, + rate: int = 10, seed: Optional[int] = None ) -> None: self.compilation_unit = compilation_unit @@ -60,7 +60,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- raise IncorrectMutatorInitialization( f"rate must be between 0 and 100 {self.__class__.__name__}" ) - + @abc.abstractmethod def _mutate(self) -> Dict: """TODO Documentation""" @@ -70,19 +70,19 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # call _mutate function from different mutators (all_patches) = self._mutate() if "patches" not in all_patches: - logger.debug(f"No patches found by {self.NAME}") + logger.debug("No patches found by %s", self.NAME) return (0,0,self.dont_mutate_line) - + for file in all_patches["patches"]: original_txt = self.slither.source_code[file].encode("utf8") patches = all_patches["patches"][file] patches.sort(key=lambda x: x["start"]) - print(yellow(f"Mutating {file} with {self.NAME} \n")) + logger.info(yellow(f"Mutating {file} with {self.NAME} \n")) for patch in patches: # test the patch flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout, self.solc_remappings, self.verbose) # if RR or CR and valid mutant, add line no. - if (self.NAME == 'RR' or self.NAME == 'CR') and flag: + if self.NAME in ('RR', 'CR') and flag: self.dont_mutate_line.append(patch['line_number']) # count the valid and invalid mutants if not flag: @@ -97,4 +97,4 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # add valid mutant patches to a output file with open(self.output_folder + "/patches_file.txt", 'a') as patches_file: patches_file.write(diff + '\n') - return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) \ No newline at end of file + return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 21925317d..852a8efc3 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -3,7 +3,7 @@ from slither.tools.mutator.mutators.MVIV import MVIV # severity low from slither.tools.mutator.mutators.MVIE import MVIE # severity low from slither.tools.mutator.mutators.LOR import LOR # severity medium from slither.tools.mutator.mutators.UOR import UOR # severity medium -from slither.tools.mutator.mutators.SBR import SBR # severity medium +from slither.tools.mutator.mutators.SBR import SBR # severity medium from slither.tools.mutator.mutators.AOR import AOR # severity medium from slither.tools.mutator.mutators.BOR import BOR # severity medium from slither.tools.mutator.mutators.ASOR import ASOR # severity medium @@ -13,4 +13,4 @@ from slither.tools.mutator.mutators.FHR import FHR # severity medium from slither.tools.mutator.mutators.MIA import MIA # severity medium from slither.tools.mutator.mutators.ROR import ROR # severity medium from slither.tools.mutator.mutators.RR import RR # severity high -from slither.tools.mutator.mutators.CR import CR # severity high \ No newline at end of file +from slither.tools.mutator.mutators.CR import CR # severity high diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index ffebee9fc..d4474c310 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -6,47 +6,49 @@ logger = logging.getLogger("Slither-Mutate") duplicated_files = {} -# function to backup the source file def backup_source_file(source_code: Dict, output_folder: str) -> Dict: + """ + function to backup the source file + returns: dictionary of duplicated files + """ os.makedirs(output_folder, exist_ok=True) - + for file_path, content in source_code.items(): directory, filename = os.path.split(file_path) new_filename = f"{output_folder}/backup_{filename}" new_file_path = os.path.join(directory, new_filename) - with open(new_file_path, 'w') as new_file: + with open(new_file_path, 'w', encoding="utf8") as new_file: new_file.write(content) duplicated_files[file_path] = new_file_path return duplicated_files -# function to transfer the original content to the sol file after campaign def transfer_and_delete(files_dict: Dict) -> None: + """function to transfer the original content to the sol file after campaign""" try: files_dict_copy = files_dict.copy() - for item, value in files_dict_copy.items(): - with open(value, 'r') as duplicated_file: + for item, value in files_dict_copy.items(): + with open(value, 'r', encoding="utf8") as duplicated_file: content = duplicated_file.read() - with open(item, 'w') as original_file: + with open(item, 'w', encoding="utf8") as original_file: original_file.write(content) os.remove(value) # delete elements from the global dict del duplicated_files[item] - - except Exception as e: + + except Exception as e: # pylint: disable=broad-except logger.error(f"Error transferring content: {e}") -#function to create new mutant file def create_mutant_file(file: str, count: int, rule: str) -> None: - + """function to create new mutant file""" try: - directory, filename = os.path.split(file) + _, filename = os.path.split(file) # Read content from the duplicated file - with open(file, 'r') as source_file: + with open(file, 'r', encoding="utf8") as source_file: content = source_file.read() # Write content to the original file @@ -54,42 +56,46 @@ def create_mutant_file(file: str, count: int, rule: str) -> None: # create folder for each contract os.makedirs("mutation_campaign/" + mutant_name, exist_ok=True) - with open("mutation_campaign/" + mutant_name + '/' + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: + with open("mutation_campaign/" + mutant_name + '/' + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w', encoding="utf8") as mutant_file: mutant_file.write(content) # reset the file - with open(duplicated_files[file], 'r') as duplicated_file: + with open(duplicated_files[file], 'r', encoding="utf8") as duplicated_file: duplicate_content = duplicated_file.read() - with open(file, 'w') as source_file: + with open(file, 'w', encoding="utf8") as source_file: source_file.write(duplicate_content) - except Exception as e: + except Exception as e: # pylint: disable=broad-except logger.error(f"Error creating mutant: {e}") -# function to reset the file def reset_file(file: str) -> None: + """function to reset the file""" try: # directory, filename = os.path.split(file) # reset the file - with open(duplicated_files[file], 'r') as duplicated_file: + with open(duplicated_files[file], 'r', encoding="utf8") as duplicated_file: duplicate_content = duplicated_file.read() - with open(file, 'w') as source_file: + with open(file, 'w', encoding="utf8") as source_file: source_file.write(duplicate_content) - except Exception as e: + except Exception as e: # pylint: disable=broad-except logger.error(f"Error resetting file: {e}") -# function to get the contracts list + def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str]: + """ + function to get the contracts list + returns: list of .sol files + """ sol_file_list = [] - if ignore_paths == None: + if ignore_paths is None: ignore_paths = [] # if input is contract file if os.path.isfile(codebase): return [codebase] - + # if input is folder elif os.path.isdir(codebase): directory = os.path.abspath(codebase) @@ -98,10 +104,10 @@ def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str if os.path.isfile(filename): sol_file_list.append(filename) elif os.path.isdir(filename): - directory_name, dirname = os.path.split(filename) + _, dirname = os.path.split(filename) if dirname in ignore_paths: - continue + continue for i in get_sol_file_list(filename, ignore_paths): sol_file_list.append(i) - return sol_file_list \ No newline at end of file + return sol_file_list diff --git a/slither/tools/mutator/utils/patch.py b/slither/tools/mutator/utils/patch.py index 39c77f673..e50f44612 100644 --- a/slither/tools/mutator/utils/patch.py +++ b/slither/tools/mutator/utils/patch.py @@ -19,4 +19,4 @@ def create_patch_with_line( if "patches" not in result: result["patches"] = defaultdict(list) if p not in result["patches"][file]: - result["patches"][file].append(p) \ No newline at end of file + result["patches"][file].append(p) diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 8525e2808..5c75f0eb3 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -1,34 +1,48 @@ -import crytic_compile import subprocess import os import logging import time import signal from typing import Dict +import crytic_compile from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_file from slither.utils.colors import green, red logger = logging.getLogger("Slither-Mutate") -# function to compile the generated mutant def compile_generated_mutant(file_path: str, mappings: str) -> bool: + """ + function to compile the generated mutant + returns: status of compilation + """ try: crytic_compile.CryticCompile(file_path, solc_remaps=mappings) return True - except: # pylint: disable=broad-except + except: # pylint: disable=bare-except return False - + def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: + """ + function to run codebase tests + returns: boolean whether the tests passed or not + """ # add --fail-fast for foundry tests, to exit after first failure - if "forge test" in cmd and not "--fail-fast" in cmd: + if "forge test" in cmd and "--fail-fast" not in cmd: cmd += " --fail-fast" # add --bail for hardhat and truffle tests, to exit after first failure - elif "hardhat test" in cmd or "truffle test" and not "--bail" in cmd: + elif "hardhat test" in cmd or "truffle test" in cmd and "--bail" not in cmd: cmd += " --bail" start = time.time() + # starting new process - P = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid) + P = subprocess.Popen( + [cmd], + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + preexec_fn=os.setsid + ) try: # checking whether the process is completed or not within 30 seconds(default) while P.poll() is None and (time.time() - start) < timeout: @@ -37,30 +51,34 @@ def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: if P.poll() is None: logger.error("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") # sends a SIGTERM signal to process group - bascially killing the process - os.killpg(os.getpgid(P.pid), signal.SIGTERM) + os.killpg(os.getpgid(P.pid), signal.SIGTERM) # Avoid any weird race conditions from grabbing the return code time.sleep(0.05) # indicates whether the command executed sucessfully or not r = P.returncode # if r is 0 then it is valid mutant because tests didn't fail - return True if r == 0 else False + return r == 0 -def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int, mappings: str | None, verbose: bool) -> bool: - with open(file, 'r') as filepath: +def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int, mappings: str | None, verbose: bool) -> bool: # pylint: disable=too-many-arguments + """ + function to verify the validity of each patch + returns: valid or invalid patch + """ + with open(file, 'r', encoding="utf-8") as filepath: content = filepath.read() # Perform the replacement based on the index values replaced_content = content[:patch['start']] + patch['new_string'] + content[patch['end']:] # Write the modified content back to the file - with open(file, 'w') as filepath: + with open(file, 'w', encoding="utf-8") as filepath: filepath.write(replaced_content) - if(compile_generated_mutant(file, mappings)): - if(run_test_cmd(command, file, timeout)): + if compile_generated_mutant(file, mappings): + if run_test_cmd(command, file, timeout): create_mutant_file(file, index, generator_name) - logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) + print(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) return True - + reset_file(file) if verbose: - logger.info(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> INVALID\n")) - return False \ No newline at end of file + print(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> INVALID\n")) + return False From f0bb9d35674c822e3397392a912ecef4a7f40d12 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Thu, 25 Jan 2024 19:22:08 -0500 Subject: [PATCH 25/64] Updated with formatting --- slither/tools/mutator/__main__.py | 90 +++++++++++------- slither/tools/mutator/mutators/AOR.py | 19 +++- slither/tools/mutator/mutators/ASOR.py | 29 ++++-- slither/tools/mutator/mutators/BOR.py | 17 +++- slither/tools/mutator/mutators/CR.py | 22 ++++- slither/tools/mutator/mutators/FHR.py | 21 +++-- slither/tools/mutator/mutators/LIR.py | 35 ++++--- slither/tools/mutator/mutators/LOR.py | 15 ++- slither/tools/mutator/mutators/MIA.py | 24 ++++- slither/tools/mutator/mutators/MVIE.py | 11 ++- slither/tools/mutator/mutators/MVIV.py | 7 +- slither/tools/mutator/mutators/MWA.py | 14 ++- slither/tools/mutator/mutators/ROR.py | 20 +++- slither/tools/mutator/mutators/RR.py | 23 ++++- slither/tools/mutator/mutators/SBR.py | 93 ++++++++++++------- slither/tools/mutator/mutators/UOR.py | 58 ++++++++++-- .../mutator/mutators/abstract_mutator.py | 48 +++++++--- .../tools/mutator/mutators/all_mutators.py | 30 +++--- slither/tools/mutator/utils/command_line.py | 3 +- slither/tools/mutator/utils/file_handling.py | 45 ++++++--- slither/tools/mutator/utils/patch.py | 11 ++- .../mutator/utils/testing_generated_mutant.py | 74 +++++++++------ 22 files changed, 504 insertions(+), 205 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 56582d6f5..f0b5c88bc 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -11,7 +11,11 @@ from slither.tools.mutator.mutators import all_mutators from slither.utils.colors import yellow, magenta from .mutators.abstract_mutator import AbstractMutator from .utils.command_line import output_mutators -from .utils.file_handling import transfer_and_delete, backup_source_file, get_sol_file_list +from .utils.file_handling import ( + transfer_and_delete, + backup_source_file, + get_sol_file_list, +) logging.basicConfig() logger = logging.getLogger("Slither-Mutate") @@ -23,6 +27,7 @@ logger.setLevel(logging.INFO) ################################################################################### ################################################################################### + def parse_args() -> argparse.Namespace: """ Parse the underlying arguments for the program. @@ -33,7 +38,9 @@ def parse_args() -> argparse.Namespace: usage="slither-mutate --test-cmd ", ) - parser.add_argument("codebase", help="Codebase to analyze (.sol file, project directory, ...)") + parser.add_argument( + "codebase", help="Codebase to analyze (.sol file, project directory, ...)" + ) parser.add_argument( "--list-mutators", @@ -44,33 +51,22 @@ def parse_args() -> argparse.Namespace: ) # argument to add the test command - parser.add_argument( - "--test-cmd", - help="Command to run the tests for your project" - ) + parser.add_argument("--test-cmd", help="Command to run the tests for your project") # argument to add the test directory - containing all the tests - parser.add_argument( - "--test-dir", - help="Tests directory" - ) + parser.add_argument("--test-dir", help="Tests directory") # argument to ignore the interfaces, libraries - parser.add_argument( - "--ignore-dirs", - help="Directories to ignore" - ) + parser.add_argument("--ignore-dirs", help="Directories to ignore") # time out argument parser.add_argument( - "--timeout", - help="Set timeout for test command (by default 30 seconds)" + "--timeout", help="Set timeout for test command (by default 30 seconds)" ) # output directory argument parser.add_argument( - "--output-dir", - help="Name of output directory (by default 'mutation_campaign')" + "--output-dir", help="Name of output directory (by default 'mutation_campaign')" ) # to print just all the mutants @@ -110,14 +106,26 @@ def parse_args() -> argparse.Namespace: return parser.parse_args() + def _get_mutators(mutators_list: List[str] | None) -> List[Type[AbstractMutator]]: detectors_ = [getattr(all_mutators, name) for name in dir(all_mutators)] if mutators_list is not None: - detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) and str(c.NAME) in mutators_list ] + detectors = [ + c + for c in detectors_ + if inspect.isclass(c) + and issubclass(c, AbstractMutator) + and str(c.NAME) in mutators_list + ] else: - detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) ] + detectors = [ + c + for c in detectors_ + if inspect.isclass(c) and issubclass(c, AbstractMutator) + ] return detectors + class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def __call__( self, parser: Any, *args: Any, **kwargs: Any @@ -126,6 +134,7 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods output_mutators(checks) parser.exit() + # endregion ################################################################################### ################################################################################### @@ -133,7 +142,10 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods ################################################################################### ################################################################################### -def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too-many-locals + +def main() -> ( + None +): # pylint: disable=too-many-statements,too-many-branches,too-many-locals args = parse_args() # arguments @@ -151,7 +163,7 @@ def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too- logger.info(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) if paths_to_ignore: - paths_to_ignore_list = paths_to_ignore.strip('][').split(',') + paths_to_ignore_list = paths_to_ignore.strip("][").split(",") logger.info(magenta(f"Ignored paths - {', '.join(paths_to_ignore_list)} \n")) else: paths_to_ignore_list = [] @@ -179,14 +191,14 @@ def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too- for M in duplicate_list: if M.NAME == "RR": mutators_list.remove(M) - CR_RR_list.insert(0,M) + CR_RR_list.insert(0, M) elif M.NAME == "CR": mutators_list.remove(M) - CR_RR_list.insert(1,M) + CR_RR_list.insert(1, M) mutators_list = CR_RR_list + mutators_list - for filename in sol_file_list: # pylint: disable=too-many-nested-blocks - contract_name = os.path.split(filename)[1].split('.sol')[0] + for filename in sol_file_list: # pylint: disable=too-many-nested-blocks + contract_name = os.path.split(filename)[1].split(".sol")[0] # slither object sl = Slither(filename, **vars(args)) # create a backup files @@ -201,24 +213,34 @@ def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too- # mutation try: for compilation_unit_of_main_file in sl.compilation_units: - contract_instance = '' + contract_instance = "" for contract in compilation_unit_of_main_file.contracts: if contract_names is not None and contract.name in contract_names: contract_instance = contract elif str(contract.name).lower() == contract_name.lower(): contract_instance = contract - if contract_instance == '': + if contract_instance == "": logger.error("Can't find the contract") else: for M in mutators_list: - m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_instance, solc_remappings, verbose, output_folder, dont_mutate_lines) + m = M( + compilation_unit_of_main_file, + int(timeout), + test_command, + test_directory, + contract_instance, + solc_remappings, + verbose, + output_folder, + dont_mutate_lines, + ) (count_valid, count_invalid, lines_list) = m.mutate() v_count += count_valid total_count += count_valid + count_invalid dont_mutate_lines = lines_list if not quick_flag: dont_mutate_lines = [] - except Exception as e: # pylint: disable=broad-except + except Exception as e: # pylint: disable=broad-except logger.error(e) except KeyboardInterrupt: @@ -230,7 +252,13 @@ def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too- transfer_and_delete(files_dict) # output - logger.info(yellow(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n")) + logger.info( + yellow( + f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n" + ) + ) logger.info(magenta(f"Finished Mutation Campaign in '{args.codebase}' \n")) + + # endregion diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index 00506a1bb..0bf0fb2a2 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -9,20 +9,23 @@ arithmetic_operators = [ BinaryType.DIVISION, BinaryType.MULTIPLICATION, BinaryType.SUBTRACTION, - BinaryType.MODULO + BinaryType.MODULO, ] + class AOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "AOR" HELP = "Arithmetic operator replacement" def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: try: ir_expression = node.expression - except: # pylint: disable=bare-except + except: # pylint: disable=bare-except continue for ir in node.irs: if isinstance(ir, Binary) and ir.type in arithmetic_operators: @@ -39,5 +42,13 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index 0e7452594..2ff403b38 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -1,7 +1,10 @@ from typing import Dict from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator -from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation +from slither.core.expressions.assignment_operation import ( + AssignmentOperationType, + AssignmentOperation, +) assignment_operators = [ AssignmentOperationType.ASSIGN_ADDITION, @@ -14,9 +17,10 @@ assignment_operators = [ AssignmentOperationType.ASSIGN_RIGHT_SHIFT, AssignmentOperationType.ASSIGN_MULTIPLICATION, AssignmentOperationType.ASSIGN_DIVISION, - AssignmentOperationType.ASSIGN_MODULO + AssignmentOperationType.ASSIGN_MODULO, ] + class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ASOR" HELP = "Assignment Operator Replacement" @@ -24,16 +28,21 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: - if isinstance(ir.expression, AssignmentOperation) and ir.expression.type in assignment_operators: + if ( + isinstance(ir.expression, AssignmentOperation) + and ir.expression.type in assignment_operators + ): if ir.expression.type == AssignmentOperationType.ASSIGN: continue alternative_ops = assignment_operators[:] try: alternative_ops.remove(ir.expression.type) - except: # pylint: disable=bare-except + except: # pylint: disable=bare-except continue for op in alternative_ops: if op != ir.expression: @@ -44,5 +53,13 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: # Replace the expression with true new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index 9f8ca2a11..a8720a4b6 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -8,9 +8,10 @@ bitwise_operators = [ BinaryType.OR, BinaryType.LEFT_SHIFT, BinaryType.RIGHT_SHIFT, - BinaryType.CARET + BinaryType.CARET, ] + class BOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "BOR" HELP = "Bitwise Operator Replacement" @@ -18,7 +19,9 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in bitwise_operators: @@ -33,5 +36,13 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/CR.py b/slither/tools/mutator/mutators/CR.py index 296028236..ebf93bf18 100644 --- a/slither/tools/mutator/mutators/CR.py +++ b/slither/tools/mutator/mutators/CR.py @@ -6,14 +6,20 @@ from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator class CR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "CR" - HELP = 'Comment Replacement' + HELP = "Comment Replacement" def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): + if node.type not in ( + NodeType.ENTRYPOINT, + NodeType.ENDIF, + NodeType.ENDLOOP, + ): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length @@ -21,5 +27,13 @@ class CR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: new_str = "//" + old_str - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index 4560db4da..028c1916c 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -7,27 +7,36 @@ from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator function_header_replacements = [ "pure ==> view", "view ==> pure", - "(\s)(external|public|internal) ==> \\1private", - "(\s)(external|public) ==> \\1internal" + "(\\s)(external|public|internal) ==> \\1private", + "(\\s)(external|public) ==> \\1internal", ] + class FHR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "FHR" - HELP = 'Function Header Replacement' + HELP = "Function Header Replacement" def _mutate(self) -> Dict: result: Dict = {} for function in self.contract.functions_and_modifiers_declared: start = function.source_mapping.start - stop = start + function.source_mapping.content.find('{') + stop = start + function.source_mapping.content.find("{") old_str = self.in_file_str[start:stop] line_no = function.source_mapping.lines if not line_no[0] in self.dont_mutate_line: for value in function_header_replacements: - left_value = value.split(" ==> ")[0] + left_value = value.split(" ==> ", maxsplit=1)[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) is not None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index f9ef874cd..066a1fbb0 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -7,16 +7,19 @@ from slither.core.solidity_types import ElementaryType literal_replacements = [] + class LIR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LIR" HELP = "Literal Interger Replacement" - def _mutate(self) -> Dict: # pylint: disable=too-many-branches + def _mutate(self) -> Dict: # pylint: disable=too-many-branches result: Dict = {} variable: Variable # Create fault for state variables declaration - for variable in self.contract.state_variables_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + variable + ) in self.contract.state_variables_declared: if variable.initialized: # Cannot remove the initialization of constant variables if variable.is_constant: @@ -24,12 +27,16 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods if isinstance(variable.expression, Literal): if isinstance(variable.type, ElementaryType): - literal_replacements.append(variable.type.min) # append data type min value - literal_replacements.append(variable.type.max) # append data type max value + literal_replacements.append( + variable.type.min + ) # append data type min value + literal_replacements.append( + variable.type.max + ) # append data type max value if str(variable.type).startswith("uint"): - literal_replacements.append('1') + literal_replacements.append("1") elif str(variable.type).startswith("uint"): - literal_replacements.append('-1') + literal_replacements.append("-1") # Get the string start = variable.source_mapping.start stop = start + variable.source_mapping.length @@ -37,7 +44,7 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = variable.node_initialization.source_mapping.lines if not line_no[0] in self.dont_mutate_line: for value in literal_replacements: - old_value = old_str[old_str.find("=")+1:].strip() + old_value = old_str[old_str.find("=") + 1 :].strip() if old_value != value: new_str = f"{old_str.split('=')[0]}= {value}" create_patch_with_line( @@ -47,26 +54,28 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods stop, old_str, new_str, - line_no[0] + line_no[0], ) - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: if variable.initialized and isinstance(variable.expression, Literal): if isinstance(variable.type, ElementaryType): literal_replacements.append(variable.type.min) literal_replacements.append(variable.type.max) if str(variable.type).startswith("uint"): - literal_replacements.append('1') + literal_replacements.append("1") elif str(variable.type).startswith("uint"): - literal_replacements.append('-1') + literal_replacements.append("-1") start = variable.source_mapping.start stop = start + variable.source_mapping.length old_str = self.in_file_str[start:stop] line_no = variable.source_mapping.lines if not line_no[0] in self.dont_mutate_line: for new_value in literal_replacements: - old_value = old_str[old_str.find("=")+1:].strip() + old_value = old_str[old_str.find("=") + 1 :].strip() if old_value != new_value: new_str = f"{old_str.split('=')[0]}= {new_value}" create_patch_with_line( @@ -76,6 +85,6 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods stop, old_str, new_str, - line_no[0] + line_no[0], ) return result diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index 21837d81e..2d1535b1a 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -8,6 +8,7 @@ logical_operators = [ BinaryType.ANDAND, ] + class LOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LOR" HELP = "Logical Operator Replacement" @@ -15,7 +16,9 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in logical_operators: @@ -31,5 +34,13 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index a10ce1f1d..f29569f63 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -4,6 +4,7 @@ from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation + class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" HELP = '"if" construct around statement' @@ -22,10 +23,25 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true and false for value in ["true", "false"]: new_str = value - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) if not isinstance(node.expression, UnaryOperation): - new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(UnaryOperationType.BANG) + "(" + old_str + ")" + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 678b3b747..4d5f6205d 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -4,6 +4,7 @@ from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.tools.mutator.utils.patch import create_patch_with_line + class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" HELP = "variable initialization using an expression" @@ -34,12 +35,14 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no[0] + line_no[0], ) for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: - if variable.initialized and not isinstance(variable.expression, Literal): + if variable.initialized and not isinstance( + variable.expression, Literal + ): # Get the string start = variable.source_mapping.start stop = variable.expression.source_mapping.start @@ -54,6 +57,6 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no[0] + line_no[0], ) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index c82f132d7..f9e51c553 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -4,6 +4,7 @@ from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.tools.mutator.utils.patch import create_patch_with_line + class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" HELP = "variable initialization using a value" @@ -34,7 +35,7 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no[0] + line_no[0], ) for function in self.contract.functions_and_modifiers_declared: @@ -53,6 +54,6 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no[0] + line_no[0], ) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index 20447290a..9682f10ca 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -4,6 +4,7 @@ from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation + class MWA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MWA" HELP = '"while" construct around statement' @@ -21,7 +22,14 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: if not isinstance(node.expression, UnaryOperation): - new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(UnaryOperationType.BANG) + "(" + old_str + ")" + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index d59e7575a..9daae0663 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -12,6 +12,7 @@ relational_operators = [ BinaryType.NOT_EQUAL, ] + class ROR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ROR" HELP = "Relational Operator Replacement" @@ -19,11 +20,16 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in relational_operators: - if str(ir.variable_left.type) != 'address' and str(ir.variable_right) != 'address': + if ( + str(ir.variable_left.type) != "address" + and str(ir.variable_right) != "address" + ): alternative_ops = relational_operators[:] alternative_ops.remove(ir.type) for op in alternative_ops: @@ -35,5 +41,13 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/RR.py b/slither/tools/mutator/mutators/RR.py index 6bfd644e0..e285d7a3f 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -3,23 +3,36 @@ from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator + class RR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "RR" - HELP = 'Revert Replacement' + HELP = "Revert Replacement" def _mutate(self) -> Dict: result: Dict = {} for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): + if node.type not in ( + NodeType.ENTRYPOINT, + NodeType.ENDIF, + NodeType.ENDLOOP, + ): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: - if old_str != 'revert()': - new_str = 'revert()' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if old_str != "revert()": + new_str = "revert()" + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index bbdc63194..770b57180 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -6,29 +6,29 @@ from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.variables.variable import Variable solidity_rules = [ - "abi\.encode\( ==> abi.encodePacked(", - "abi\.encodePacked\( ==> abi.encode(", - "\.call([({]) ==> .delegatecall\\1", - "\.call([({]) ==> .staticcall\\1", - "\.delegatecall([({]) ==> .call\\1", - "\.delegatecall([({]) ==> .staticcall\\1", - "\.staticcall([({]) ==> .delegatecall\\1", - "\.staticcall([({]) ==> .call\\1", + "abi\\.encode\\( ==> abi.encodePacked(", + "abi\\.encodePacked\\( ==> abi.encode(", + "\\.call([({]) ==> .delegatecall\\1", + "\\.call([({]) ==> .staticcall\\1", + "\\.delegatecall([({]) ==> .call\\1", + "\\.delegatecall([({]) ==> .staticcall\\1", + "\\.staticcall([({]) ==> .delegatecall\\1", + "\\.staticcall([({]) ==> .call\\1", "^now$ ==> 0", "block.timestamp ==> 0", "msg.value ==> 0", "msg.value ==> 1", - "(\s)(wei|gwei) ==> \\1ether", - "(\s)(ether|gwei) ==> \\1wei", - "(\s)(wei|ether) ==> \\1gwei", - "(\s)(minutes|days|hours|weeks) ==> \\1seconds", - "(\s)(seconds|days|hours|weeks) ==> \\1minutes", - "(\s)(seconds|minutes|hours|weeks) ==> \\1days", - "(\s)(seconds|minutes|days|weeks) ==> \\1hours", - "(\s)(seconds|minutes|days|hours) ==> \\1weeks", - "(\s)(memory) ==> \\1storage", - "(\s)(storage) ==> \\1memory", - "(\s)(constant) ==> \\1immutable", + "(\\s)(wei|gwei) ==> \\1ether", + "(\\s)(ether|gwei) ==> \\1wei", + "(\\s)(wei|ether) ==> \\1gwei", + "(\\s)(minutes|days|hours|weeks) ==> \\1seconds", + "(\\s)(seconds|days|hours|weeks) ==> \\1minutes", + "(\\s)(seconds|minutes|hours|weeks) ==> \\1days", + "(\\s)(seconds|minutes|days|weeks) ==> \\1hours", + "(\\s)(seconds|minutes|days|hours) ==> \\1weeks", + "(\\s)(memory) ==> \\1storage", + "(\\s)(storage) ==> \\1memory", + "(\\s)(constant) ==> \\1immutable", "addmod ==> mulmod", "mulmod ==> addmod", "msg.sender ==> tx.origin", @@ -40,45 +40,74 @@ solidity_rules = [ "(u?)int64 ==> \\1int32", "(u?)int128 ==> \\1int64", "(u?)int256 ==> \\1int128", - "while ==> if", + "while ==> if", ] + class SBR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "SBR" - HELP = 'Solidity Based Replacement' + HELP = "Solidity Based Replacement" def _mutate(self) -> Dict: result: Dict = {} variable: Variable - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): + if node.type not in ( + NodeType.ENTRYPOINT, + NodeType.ENDIF, + NodeType.ENDLOOP, + ): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = self.in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: for value in solidity_rules: - left_value = value.split(" ==> ")[0] + left_value = value.split(" ==> ", maxsplit=1)[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) is not None: - new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = re.sub( + re.compile(left_value), right_value, old_str + ) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) - for variable in self.contract.state_variables_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + variable + ) in self.contract.state_variables_declared: node = variable.node_initialization if node: start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = self.in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: for value in solidity_rules: - left_value = value.split(" ==> ")[0] + left_value = value.split(" ==> ", maxsplit=1)[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) is not None: - new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = re.sub( + re.compile(left_value), right_value, old_str + ) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/UOR.py b/slither/tools/mutator/mutators/UOR.py index b7e8c8156..f427c2fbf 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -8,9 +8,10 @@ unary_operators = [ UnaryOperationType.MINUSMINUS_PRE, UnaryOperationType.PLUSPLUS_POST, UnaryOperationType.MINUSMINUS_POST, - UnaryOperationType.MINUS_PRE + UnaryOperationType.MINUS_PRE, ] + class UOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "UOR" HELP = "Unary Operator Replacement" @@ -18,33 +19,70 @@ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: try: ir_expression = node.expression - except: # pylint: disable=bare-except + except: # pylint: disable=bare-except continue start = node.source_mapping.start stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: - if isinstance(ir_expression, UnaryOperation) and ir_expression.type in unary_operators: + if ( + isinstance(ir_expression, UnaryOperation) + and ir_expression.type in unary_operators + ): for op in unary_operators: if not node.expression.is_prefix: if node.expression.type != op: variable_read = node.variables_read[0] new_str = str(variable_read) + str(op) - if new_str != old_str and str(op) != '-': - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if new_str != old_str and str(op) != "-": + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) new_str = str(op) + str(variable_read) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) else: if node.expression.type != op: variable_read = node.variables_read[0] new_str = str(op) + str(variable_read) - if new_str != old_str and str(op) != '-': - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if new_str != old_str and str(op) != "-": + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) new_str = str(variable_read) + str(op) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index c2f15cd74..12c6b2298 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -9,17 +9,22 @@ from slither.core.declarations import Contract logger = logging.getLogger("Slither-Mutate") + class IncorrectMutatorInitialization(Exception): pass -class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public-methods + +class AbstractMutator( + metaclass=abc.ABCMeta +): # pylint: disable=too-few-public-methods,too-many-instance-attributes NAME = "" HELP = "" VALID_MUTANTS_COUNT = 0 INVALID_MUTANTS_COUNT = 0 - def __init__( # pylint: disable=too-many-arguments - self, compilation_unit: SlitherCompilationUnit, + def __init__( # pylint: disable=too-many-arguments + self, + compilation_unit: SlitherCompilationUnit, timeout: int, testing_command: str, testing_directory: str, @@ -29,7 +34,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- output_folder: str, dont_mutate_line: List[int], rate: int = 10, - seed: Optional[int] = None + seed: Optional[int] = None, ) -> None: self.compilation_unit = compilation_unit self.slither = compilation_unit.core @@ -71,7 +76,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- (all_patches) = self._mutate() if "patches" not in all_patches: logger.debug("No patches found by %s", self.NAME) - return (0,0,self.dont_mutate_line) + return (0, 0, self.dont_mutate_line) for file in all_patches["patches"]: original_txt = self.slither.source_code[file].encode("utf8") @@ -80,21 +85,38 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- logger.info(yellow(f"Mutating {file} with {self.NAME} \n")) for patch in patches: # test the patch - flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout, self.solc_remappings, self.verbose) + flag = test_patch( + file, + patch, + self.test_command, + self.VALID_MUTANTS_COUNT, + self.NAME, + self.timeout, + self.solc_remappings, + self.verbose, + ) # if RR or CR and valid mutant, add line no. - if self.NAME in ('RR', 'CR') and flag: - self.dont_mutate_line.append(patch['line_number']) + if self.NAME in ("RR", "CR") and flag: + self.dont_mutate_line.append(patch["line_number"]) # count the valid and invalid mutants if not flag: self.INVALID_MUTANTS_COUNT += 1 continue self.VALID_MUTANTS_COUNT += 1 - patched_txt,_ = apply_patch(original_txt, patch, 0) - diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) + patched_txt, _ = apply_patch(original_txt, patch, 0) + diff = create_diff( + self.compilation_unit, original_txt, patched_txt, file + ) if not diff: logger.info(f"Impossible to generate patch; empty {patches}") # add valid mutant patches to a output file - with open(self.output_folder + "/patches_file.txt", 'a') as patches_file: - patches_file.write(diff + '\n') - return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) + with open( + self.output_folder + "/patches_file.txt", "a", encoding="utf8" + ) as patches_file: + patches_file.write(diff + "\n") + return ( + self.VALID_MUTANTS_COUNT, + self.INVALID_MUTANTS_COUNT, + self.dont_mutate_line, + ) diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 852a8efc3..b02a2cc9b 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -1,16 +1,16 @@ # pylint: disable=unused-import -from slither.tools.mutator.mutators.MVIV import MVIV # severity low -from slither.tools.mutator.mutators.MVIE import MVIE # severity low -from slither.tools.mutator.mutators.LOR import LOR # severity medium -from slither.tools.mutator.mutators.UOR import UOR # severity medium -from slither.tools.mutator.mutators.SBR import SBR # severity medium -from slither.tools.mutator.mutators.AOR import AOR # severity medium -from slither.tools.mutator.mutators.BOR import BOR # severity medium -from slither.tools.mutator.mutators.ASOR import ASOR # severity medium -from slither.tools.mutator.mutators.MWA import MWA # severity medium -from slither.tools.mutator.mutators.LIR import LIR # severity medium -from slither.tools.mutator.mutators.FHR import FHR # severity medium -from slither.tools.mutator.mutators.MIA import MIA # severity medium -from slither.tools.mutator.mutators.ROR import ROR # severity medium -from slither.tools.mutator.mutators.RR import RR # severity high -from slither.tools.mutator.mutators.CR import CR # severity high +from slither.tools.mutator.mutators.MVIV import MVIV # severity low +from slither.tools.mutator.mutators.MVIE import MVIE # severity low +from slither.tools.mutator.mutators.LOR import LOR # severity medium +from slither.tools.mutator.mutators.UOR import UOR # severity medium +from slither.tools.mutator.mutators.SBR import SBR # severity medium +from slither.tools.mutator.mutators.AOR import AOR # severity medium +from slither.tools.mutator.mutators.BOR import BOR # severity medium +from slither.tools.mutator.mutators.ASOR import ASOR # severity medium +from slither.tools.mutator.mutators.MWA import MWA # severity medium +from slither.tools.mutator.mutators.LIR import LIR # severity medium +from slither.tools.mutator.mutators.FHR import FHR # severity medium +from slither.tools.mutator.mutators.MIA import MIA # severity medium +from slither.tools.mutator.mutators.ROR import ROR # severity medium +from slither.tools.mutator.mutators.RR import RR # severity high +from slither.tools.mutator.mutators.CR import CR # severity high diff --git a/slither/tools/mutator/utils/command_line.py b/slither/tools/mutator/utils/command_line.py index 358586688..79d705097 100644 --- a/slither/tools/mutator/utils/command_line.py +++ b/slither/tools/mutator/utils/command_line.py @@ -2,6 +2,7 @@ from typing import List, Type from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.utils.myprettytable import MyPrettyTable + def output_mutators(mutators_classes: List[Type[AbstractMutator]]) -> None: mutators_list = [] for detector in mutators_classes: @@ -13,7 +14,7 @@ def output_mutators(mutators_classes: List[Type[AbstractMutator]]) -> None: # Sort by class mutators_list = sorted(mutators_list, key=lambda element: (element[0])) idx = 1 - for (argument, help_info) in mutators_list: + for argument, help_info in mutators_list: table.add_row([str(idx), argument, help_info]) idx = idx + 1 print(table) diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index d4474c310..ddb3efb50 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -6,6 +6,7 @@ logger = logging.getLogger("Slither-Mutate") duplicated_files = {} + def backup_source_file(source_code: Dict, output_folder: str) -> Dict: """ function to backup the source file @@ -18,21 +19,22 @@ def backup_source_file(source_code: Dict, output_folder: str) -> Dict: new_filename = f"{output_folder}/backup_{filename}" new_file_path = os.path.join(directory, new_filename) - with open(new_file_path, 'w', encoding="utf8") as new_file: + with open(new_file_path, "w", encoding="utf8") as new_file: new_file.write(content) duplicated_files[file_path] = new_file_path return duplicated_files + def transfer_and_delete(files_dict: Dict) -> None: """function to transfer the original content to the sol file after campaign""" try: files_dict_copy = files_dict.copy() for item, value in files_dict_copy.items(): - with open(value, 'r', encoding="utf8") as duplicated_file: + with open(value, "r", encoding="utf8") as duplicated_file: content = duplicated_file.read() - with open(item, 'w', encoding="utf8") as original_file: + with open(item, "w", encoding="utf8") as original_file: original_file.write(content) os.remove(value) @@ -40,47 +42,61 @@ def transfer_and_delete(files_dict: Dict) -> None: # delete elements from the global dict del duplicated_files[item] - except Exception as e: # pylint: disable=broad-except + except Exception as e: # pylint: disable=broad-except logger.error(f"Error transferring content: {e}") + def create_mutant_file(file: str, count: int, rule: str) -> None: """function to create new mutant file""" try: _, filename = os.path.split(file) # Read content from the duplicated file - with open(file, 'r', encoding="utf8") as source_file: + with open(file, "r", encoding="utf8") as source_file: content = source_file.read() # Write content to the original file - mutant_name = filename.split('.')[0] + mutant_name = filename.split(".")[0] # create folder for each contract os.makedirs("mutation_campaign/" + mutant_name, exist_ok=True) - with open("mutation_campaign/" + mutant_name + '/' + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w', encoding="utf8") as mutant_file: + with open( + "mutation_campaign/" + + mutant_name + + "/" + + mutant_name + + "_" + + rule + + "_" + + str(count) + + ".sol", + "w", + encoding="utf8", + ) as mutant_file: mutant_file.write(content) # reset the file - with open(duplicated_files[file], 'r', encoding="utf8") as duplicated_file: + with open(duplicated_files[file], "r", encoding="utf8") as duplicated_file: duplicate_content = duplicated_file.read() - with open(file, 'w', encoding="utf8") as source_file: + with open(file, "w", encoding="utf8") as source_file: source_file.write(duplicate_content) - except Exception as e: # pylint: disable=broad-except + except Exception as e: # pylint: disable=broad-except logger.error(f"Error creating mutant: {e}") + def reset_file(file: str) -> None: """function to reset the file""" try: # directory, filename = os.path.split(file) # reset the file - with open(duplicated_files[file], 'r', encoding="utf8") as duplicated_file: + with open(duplicated_files[file], "r", encoding="utf8") as duplicated_file: duplicate_content = duplicated_file.read() - with open(file, 'w', encoding="utf8") as source_file: + with open(file, "w", encoding="utf8") as source_file: source_file.write(duplicate_content) - except Exception as e: # pylint: disable=broad-except + except Exception as e: # pylint: disable=broad-except logger.error(f"Error resetting file: {e}") @@ -92,12 +108,13 @@ def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str sol_file_list = [] if ignore_paths is None: ignore_paths = [] + # if input is contract file if os.path.isfile(codebase): return [codebase] # if input is folder - elif os.path.isdir(codebase): + if os.path.isdir(codebase): directory = os.path.abspath(codebase) for file in os.listdir(directory): filename = os.path.join(directory, file) diff --git a/slither/tools/mutator/utils/patch.py b/slither/tools/mutator/utils/patch.py index e50f44612..54ff81e60 100644 --- a/slither/tools/mutator/utils/patch.py +++ b/slither/tools/mutator/utils/patch.py @@ -1,6 +1,7 @@ from typing import Dict, Union from collections import defaultdict + # pylint: disable=too-many-arguments def create_patch_with_line( result: Dict, @@ -9,13 +10,19 @@ def create_patch_with_line( end: int, old_str: Union[str, bytes], new_str: Union[str, bytes], - line_no: int + line_no: int, ) -> None: if isinstance(old_str, bytes): old_str = old_str.decode("utf8") if isinstance(new_str, bytes): new_str = new_str.decode("utf8") - p = {"start": start, "end": end, "old_string": old_str, "new_string": new_str, "line_number": line_no} + p = { + "start": start, + "end": end, + "old_string": old_str, + "new_string": new_str, + "line_number": line_no, + } if "patches" not in result: result["patches"] = defaultdict(list) if p not in result["patches"][file]: diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 5c75f0eb3..0e495f8ae 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -10,6 +10,7 @@ from slither.utils.colors import green, red logger = logging.getLogger("Slither-Mutate") + def compile_generated_mutant(file_path: str, mappings: str) -> bool: """ function to compile the generated mutant @@ -21,11 +22,14 @@ def compile_generated_mutant(file_path: str, mappings: str) -> bool: except: # pylint: disable=bare-except return False -def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: + +def run_test_cmd(cmd: str, test_dir: str, timeout: int) -> bool: """ function to run codebase tests returns: boolean whether the tests passed or not """ + # future purpose + _ = test_dir # add --fail-fast for foundry tests, to exit after first failure if "forge test" in cmd and "--fail-fast" not in cmd: cmd += " --fail-fast" @@ -36,49 +40,65 @@ def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: start = time.time() # starting new process - P = subprocess.Popen( - [cmd], - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - preexec_fn=os.setsid - ) - try: - # checking whether the process is completed or not within 30 seconds(default) - while P.poll() is None and (time.time() - start) < timeout: - time.sleep(0.05) - finally: - if P.poll() is None: - logger.error("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") - # sends a SIGTERM signal to process group - bascially killing the process - os.killpg(os.getpgid(P.pid), signal.SIGTERM) - # Avoid any weird race conditions from grabbing the return code - time.sleep(0.05) - # indicates whether the command executed sucessfully or not - r = P.returncode + with subprocess.Popen( + [cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) as P: + try: + # checking whether the process is completed or not within 30 seconds(default) + while P.poll() is None and (time.time() - start) < timeout: + time.sleep(0.05) + finally: + if P.poll() is None: + logger.error("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") + # sends a SIGTERM signal to process group - bascially killing the process + os.killpg(os.getpgid(P.pid), signal.SIGTERM) + # Avoid any weird race conditions from grabbing the return code + time.sleep(0.05) + # indicates whether the command executed sucessfully or not + r = P.returncode # if r is 0 then it is valid mutant because tests didn't fail return r == 0 -def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int, mappings: str | None, verbose: bool) -> bool: # pylint: disable=too-many-arguments + +def test_patch( # pylint: disable=too-many-arguments + file: str, + patch: Dict, + command: str, + index: int, + generator_name: str, + timeout: int, + mappings: str | None, + verbose: bool, +) -> bool: """ function to verify the validity of each patch returns: valid or invalid patch """ - with open(file, 'r', encoding="utf-8") as filepath: + with open(file, "r", encoding="utf-8") as filepath: content = filepath.read() # Perform the replacement based on the index values - replaced_content = content[:patch['start']] + patch['new_string'] + content[patch['end']:] + replaced_content = ( + content[: patch["start"]] + patch["new_string"] + content[patch["end"] :] + ) # Write the modified content back to the file - with open(file, 'w', encoding="utf-8") as filepath: + with open(file, "w", encoding="utf-8") as filepath: filepath.write(replaced_content) if compile_generated_mutant(file, mappings): if run_test_cmd(command, file, timeout): create_mutant_file(file, index, generator_name) - print(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) + print( + green( + f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n" + ) + ) return True reset_file(file) if verbose: - print(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> INVALID\n")) + print( + red( + f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> INVALID\n" + ) + ) return False From 611150bef45fb94f67088afb3100fdf42c0ec19b Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 26 Jan 2024 16:19:48 +0100 Subject: [PATCH 26/64] Add support Solidity 0.8.24 --- slither/core/declarations/solidity_variables.py | 3 +++ slither/solc_parsing/yul/evm_functions.py | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index 7c81266bf..9b8ae3f03 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -22,6 +22,7 @@ SOLIDITY_VARIABLES = { SOLIDITY_VARIABLES_COMPOSED = { "block.basefee": "uint", + "block.blobbasefee": "uint256", "block.coinbase": "address", "block.difficulty": "uint256", "block.prevrandao": "uint256", @@ -44,6 +45,8 @@ SOLIDITY_VARIABLES_COMPOSED = { } SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { + + "blobhash(uint256)": ["bytes32"], "gasleft()": ["uint256"], "assert(bool)": [], "require(bool)": [], diff --git a/slither/solc_parsing/yul/evm_functions.py b/slither/solc_parsing/yul/evm_functions.py index 28ea70e93..11f79b4ce 100644 --- a/slither/solc_parsing/yul/evm_functions.py +++ b/slither/solc_parsing/yul/evm_functions.py @@ -1,7 +1,7 @@ from slither.core.declarations.solidity_variables import SOLIDITY_FUNCTIONS from slither.core.expressions import BinaryOperationType, UnaryOperationType -# taken from https://github.com/ethereum/solidity/blob/356cc91084114f840da66804b2a9fc1ac2846cff/libevmasm/Instruction.cpp#L180 +# taken from https://github.com/ethereum/solidity/blob/e11b9ed9f2c254bc894d844c0a64a0eb76bbb4fd/libevmasm/Instruction.cpp#L184 evm_opcodes = [ "STOP", "ADD", @@ -45,6 +45,7 @@ evm_opcodes = [ "EXTCODECOPY", "RETURNDATASIZE", "RETURNDATACOPY", + "MCOPY", "EXTCODEHASH", "BLOCKHASH", "COINBASE", @@ -55,12 +56,16 @@ evm_opcodes = [ "GASLIMIT", "CHAINID", "SELFBALANCE", + "BLOBHASH", + "BLOBBASEFEE", "POP", "MLOAD", "MSTORE", "MSTORE8", "SLOAD", "SSTORE", + "TLOAD", + "TSTORE", "JUMP", "JUMPI", "PC", @@ -183,11 +188,15 @@ function_args = { "mstore8": [2, 0], "sload": [1, 1], "sstore": [2, 0], + "tload": [1, 1], + "tstore": [2, 0], "msize": [1, 1], "gas": [0, 1], "address": [0, 1], "balance": [1, 1], "selfbalance": [0, 1], + "blobhash": [1, 1], + "blobbasefee": [0, 1], "caller": [0, 1], "callvalue": [0, 1], "calldataload": [1, 1], @@ -199,6 +208,7 @@ function_args = { "extcodecopy": [4, 0], "returndatasize": [0, 1], "returndatacopy": [3, 0], + "mcopy": [3, 0], "extcodehash": [1, 1], "create": [3, 1], "create2": [4, 1], From 0dcab3bbdd82045a56b6053359dd5372d9d829e0 Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 26 Jan 2024 16:21:54 +0100 Subject: [PATCH 27/64] Add BASEFEE for Yul --- slither/core/declarations/solidity_variables.py | 2 +- slither/solc_parsing/yul/evm_functions.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index 9b8ae3f03..86bdb5bd2 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -21,7 +21,7 @@ SOLIDITY_VARIABLES = { } SOLIDITY_VARIABLES_COMPOSED = { - "block.basefee": "uint", + "block.basefee": "uint256", "block.blobbasefee": "uint256", "block.coinbase": "address", "block.difficulty": "uint256", diff --git a/slither/solc_parsing/yul/evm_functions.py b/slither/solc_parsing/yul/evm_functions.py index 11f79b4ce..23df6e85f 100644 --- a/slither/solc_parsing/yul/evm_functions.py +++ b/slither/solc_parsing/yul/evm_functions.py @@ -56,6 +56,7 @@ evm_opcodes = [ "GASLIMIT", "CHAINID", "SELFBALANCE", + "BASEFEE", "BLOBHASH", "BLOBBASEFEE", "POP", @@ -195,6 +196,7 @@ function_args = { "address": [0, 1], "balance": [1, 1], "selfbalance": [0, 1], + "basefee": [0, 1], "blobhash": [1, 1], "blobbasefee": [0, 1], "caller": [0, 1], From a8cb6bed86c48d1a397066c299cb81a443da3f96 Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 26 Jan 2024 16:24:43 +0100 Subject: [PATCH 28/64] Lint --- slither/core/declarations/solidity_variables.py | 1 - 1 file changed, 1 deletion(-) diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index 86bdb5bd2..2d77a20c0 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -45,7 +45,6 @@ SOLIDITY_VARIABLES_COMPOSED = { } SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { - "blobhash(uint256)": ["bytes32"], "gasleft()": ["uint256"], "assert(bool)": [], From c5f1537022be4f5301c3f986d6fa1a94681db1a1 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Fri, 26 Jan 2024 11:37:05 -0500 Subject: [PATCH 29/64] Formatted mutators --- slither/tools/mutator/__main__.py | 18 ++++-------------- slither/tools/mutator/mutators/LIR.py | 8 ++------ slither/tools/mutator/mutators/MVIE.py | 4 +--- slither/tools/mutator/mutators/SBR.py | 8 ++------ .../tools/mutator/mutators/abstract_mutator.py | 4 +--- .../mutator/utils/testing_generated_mutant.py | 8 ++------ 6 files changed, 12 insertions(+), 38 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index f0b5c88bc..5c13d7aea 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -38,9 +38,7 @@ def parse_args() -> argparse.Namespace: usage="slither-mutate --test-cmd ", ) - parser.add_argument( - "codebase", help="Codebase to analyze (.sol file, project directory, ...)" - ) + parser.add_argument("codebase", help="Codebase to analyze (.sol file, project directory, ...)") parser.add_argument( "--list-mutators", @@ -60,9 +58,7 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--ignore-dirs", help="Directories to ignore") # time out argument - parser.add_argument( - "--timeout", help="Set timeout for test command (by default 30 seconds)" - ) + parser.add_argument("--timeout", help="Set timeout for test command (by default 30 seconds)") # output directory argument parser.add_argument( @@ -118,11 +114,7 @@ def _get_mutators(mutators_list: List[str] | None) -> List[Type[AbstractMutator] and str(c.NAME) in mutators_list ] else: - detectors = [ - c - for c in detectors_ - if inspect.isclass(c) and issubclass(c, AbstractMutator) - ] + detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator)] return detectors @@ -143,9 +135,7 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods ################################################################################### -def main() -> ( - None -): # pylint: disable=too-many-statements,too-many-branches,too-many-locals +def main() -> (None): # pylint: disable=too-many-statements,too-many-branches,too-many-locals args = parse_args() # arguments diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index 066a1fbb0..cc58cbae1 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -27,12 +27,8 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods if isinstance(variable.expression, Literal): if isinstance(variable.type, ElementaryType): - literal_replacements.append( - variable.type.min - ) # append data type min value - literal_replacements.append( - variable.type.max - ) # append data type max value + literal_replacements.append(variable.type.min) # append data type min value + literal_replacements.append(variable.type.max) # append data type max value if str(variable.type).startswith("uint"): literal_replacements.append("1") elif str(variable.type).startswith("uint"): diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 4d5f6205d..ce51792ff 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -40,9 +40,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: - if variable.initialized and not isinstance( - variable.expression, Literal - ): + if variable.initialized and not isinstance(variable.expression, Literal): # Get the string start = variable.source_mapping.start stop = variable.expression.source_mapping.start diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index 770b57180..efbda4877 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -71,9 +71,7 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods left_value = value.split(" ==> ", maxsplit=1)[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) is not None: - new_str = re.sub( - re.compile(left_value), right_value, old_str - ) + new_str = re.sub(re.compile(left_value), right_value, old_str) create_patch_with_line( result, self.in_file, @@ -98,9 +96,7 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods left_value = value.split(" ==> ", maxsplit=1)[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) is not None: - new_str = re.sub( - re.compile(left_value), right_value, old_str - ) + new_str = re.sub(re.compile(left_value), right_value, old_str) create_patch_with_line( result, self.in_file, diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index 12c6b2298..375af1e6f 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -104,9 +104,7 @@ class AbstractMutator( continue self.VALID_MUTANTS_COUNT += 1 patched_txt, _ = apply_patch(original_txt, patch, 0) - diff = create_diff( - self.compilation_unit, original_txt, patched_txt, file - ) + diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) if not diff: logger.info(f"Impossible to generate patch; empty {patches}") diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 0e495f8ae..6104cdd8a 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -40,9 +40,7 @@ def run_test_cmd(cmd: str, test_dir: str, timeout: int) -> bool: start = time.time() # starting new process - with subprocess.Popen( - [cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) as P: + with subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as P: try: # checking whether the process is completed or not within 30 seconds(default) while P.poll() is None and (time.time() - start) < timeout: @@ -78,9 +76,7 @@ def test_patch( # pylint: disable=too-many-arguments with open(file, "r", encoding="utf-8") as filepath: content = filepath.read() # Perform the replacement based on the index values - replaced_content = ( - content[: patch["start"]] + patch["new_string"] + content[patch["end"] :] - ) + replaced_content = (content[: patch["start"]] + patch["new_string"] + content[patch["end"] :]) # Write the modified content back to the file with open(file, "w", encoding="utf-8") as filepath: filepath.write(replaced_content) From 360509f8185d9915c98a66fefc0a9c91b30d8f84 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Fri, 26 Jan 2024 12:25:32 -0500 Subject: [PATCH 30/64] Formatted test_patch --- slither/tools/mutator/utils/testing_generated_mutant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 6104cdd8a..4c51b7e5a 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -76,7 +76,7 @@ def test_patch( # pylint: disable=too-many-arguments with open(file, "r", encoding="utf-8") as filepath: content = filepath.read() # Perform the replacement based on the index values - replaced_content = (content[: patch["start"]] + patch["new_string"] + content[patch["end"] :]) + replaced_content = content[: patch["start"]] + patch["new_string"] + content[patch["end"] :] # Write the modified content back to the file with open(file, "w", encoding="utf-8") as filepath: filepath.write(replaced_content) From d6e40afc5ede852624693490111adbc94d13c030 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:41:54 -0600 Subject: [PATCH 31/64] Bump cachix/cachix-action from 12 to 14 (#2275) Bumps [cachix/cachix-action](https://github.com/cachix/cachix-action) from 12 to 14. - [Release notes](https://github.com/cachix/cachix-action/releases) - [Commits](https://github.com/cachix/cachix-action/compare/v12...v14) --- updated-dependencies: - dependency-name: cachix/cachix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a646bb42..9675b0d35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: - name: Set up cachix if: matrix.type == 'dapp' - uses: cachix/cachix-action@v12 + uses: cachix/cachix-action@v14 with: name: dapp From 340cbe09a6f58a8bfe48b37d93653c6a8d3293cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:42:07 -0600 Subject: [PATCH 32/64] Bump actions/upload-artifact from 3 to 4 (#2265) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e0ab4b543..dd63b5f47 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -23,7 +23,7 @@ jobs: python -m pip install build python -m build - name: Upload distributions - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: slither-dists path: dist/ From b83fa21b3e1fbfbc5b92b780960ba0de084d83c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:42:16 -0600 Subject: [PATCH 33/64] Bump actions/setup-python from 4 to 5 (#2259) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/black.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/docs.yml | 2 +- .github/workflows/doctor.yml | 2 +- .github/workflows/linter.yml | 2 +- .github/workflows/pip-audit.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/pylint.yml | 2 +- .github/workflows/test.yml | 4 ++-- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index 6017255b2..082333f2f 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -32,7 +32,7 @@ jobs: fetch-depth: 0 - name: Set up Python 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.8 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9675b0d35..dbde09489 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,7 +55,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install dependencies diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e28c7136a..3d5eeed65 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: '3.8' - run: pip install -e ".[doc]" diff --git a/.github/workflows/doctor.yml b/.github/workflows/doctor.yml index 0a0eb896d..555452871 100644 --- a/.github/workflows/doctor.yml +++ b/.github/workflows/doctor.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 5415b6d1b..45dc0d8c2 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -31,7 +31,7 @@ jobs: fetch-depth: 0 - name: Set up Python 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.8 diff --git a/.github/workflows/pip-audit.yml b/.github/workflows/pip-audit.yml index a98f6ab58..1c0a1d40a 100644 --- a/.github/workflows/pip-audit.yml +++ b/.github/workflows/pip-audit.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v4 - name: Install Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index dd63b5f47..7fc17804c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 7e990371f..091da2b96 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -29,7 +29,7 @@ jobs: fetch-depth: 0 - name: Set up Python 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.8 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1660a25e9..68a32f80a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} cache: "pip" @@ -102,7 +102,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.8 From b292175837e9da2252d45ce8dd12d5769551f28d Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Mon, 29 Jan 2024 22:42:45 +0100 Subject: [PATCH 34/64] Detect also in modifiers (#2280) --- slither/detectors/statements/divide_before_multiply.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/statements/divide_before_multiply.py b/slither/detectors/statements/divide_before_multiply.py index 334da592c..1f6ccd87e 100644 --- a/slither/detectors/statements/divide_before_multiply.py +++ b/slither/detectors/statements/divide_before_multiply.py @@ -133,7 +133,7 @@ def detect_divide_before_multiply( results: List[Tuple[FunctionContract, List[Node]]] = [] # Loop for each function and modifier. - for function in contract.functions_declared: + for function in contract.functions_declared + contract.modifiers_declared: if not function.entry_point: continue From 28a921ec5dcdd25e21cf8b55903f23d4c097f631 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 29 Jan 2024 15:43:14 -0600 Subject: [PATCH 35/64] Fix/iterative update (#2206) * use iterative algo to prevent exceeding recursion limit * proper fixpoint --- slither/solc_parsing/declarations/function.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 59940ec1c..c1b94661d 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -1106,11 +1106,13 @@ class FunctionSolc(CallerContextExpression): return node def _update_reachability(self, node: Node) -> None: - if node.is_reachable: - return - node.set_is_reachable(True) - for son in node.sons: - self._update_reachability(son) + worklist = [node] + while worklist: + current = worklist.pop() + # fix point + if not current.is_reachable: + current.set_is_reachable(True) + worklist.extend(current.sons) def _parse_cfg(self, cfg: Dict) -> None: From 4454b3e34af0f21498b2a721e4698013f1100b22 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 29 Jan 2024 15:44:25 -0600 Subject: [PATCH 36/64] fix: detect selfdestruct in internal calls (#2232) * fix: detect selfdestruct in internal calls * update snapshot --- slither/detectors/functions/suicidal.py | 2 +- ...etector_Suicidal_0_7_6_suicidal_sol__0.txt | 2 ++ .../test_data/suicidal/0.7.6/suicidal.sol | 8 ++++++++ .../suicidal/0.7.6/suicidal.sol-0.7.6.zip | Bin 1478 -> 1918 bytes 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/slither/detectors/functions/suicidal.py b/slither/detectors/functions/suicidal.py index 1f8cb52f9..f0af978ec 100644 --- a/slither/detectors/functions/suicidal.py +++ b/slither/detectors/functions/suicidal.py @@ -59,7 +59,7 @@ Bob calls `kill` and destructs the contract.""" if func.visibility not in ["public", "external"]: return False - calls = [c.name for c in func.internal_calls] + calls = [c.name for c in func.all_internal_calls()] if not ("suicide(address)" in calls or "selfdestruct(address)" in calls): return False diff --git a/tests/e2e/detectors/snapshots/detectors__detector_Suicidal_0_7_6_suicidal_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_Suicidal_0_7_6_suicidal_sol__0.txt index 4a784217d..99a6a0295 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_Suicidal_0_7_6_suicidal_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_Suicidal_0_7_6_suicidal_sol__0.txt @@ -1,2 +1,4 @@ +C.i_am_a_backdoor2(address) (tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol#8-10) allows anyone to destruct the contract + C.i_am_a_backdoor() (tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol#4-6) allows anyone to destruct the contract diff --git a/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol b/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol index 428c794d4..31b22d767 100644 --- a/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol +++ b/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol @@ -5,4 +5,12 @@ contract C{ selfdestruct(msg.sender); } + function i_am_a_backdoor2(address payable to) public{ + internal_selfdestruct(to); + } + + function internal_selfdestruct(address payable to) internal { + selfdestruct(to); + } + } diff --git a/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol-0.7.6.zip b/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol-0.7.6.zip index 635092d49ecdda4ce21c4da09b8ba5b061e9a72e..ecd80364b245bf08dcb196de7486ec55a28df991 100644 GIT binary patch delta 1676 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 Date: Tue, 30 Jan 2024 08:36:21 -0600 Subject: [PATCH 37/64] Bump actions/deploy-pages from 3 to 4 (#2285) Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 3 to 4. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 3d5eeed65..4292d5f44 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -43,4 +43,4 @@ jobs: path: './html/' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v3 + uses: actions/deploy-pages@v4 From 1bd279a0179fe1ec52f98f02e736cce3ed39c53c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 08:36:32 -0600 Subject: [PATCH 38/64] Bump cachix/install-nix-action from 24 to 25 (#2286) Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 24 to 25. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/v24...v25) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbde09489..7972c96e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: - name: Set up nix if: matrix.type == 'dapp' - uses: cachix/install-nix-action@v24 + uses: cachix/install-nix-action@v25 - name: Set up cachix if: matrix.type == 'dapp' From 1b0d63b428ac7c66c70ae359fdfa220b445166a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 07:46:35 -0600 Subject: [PATCH 39/64] Bump sigstore/gh-action-sigstore-python from 2.1.0 to 2.1.1 (#2293) Bumps [sigstore/gh-action-sigstore-python](https://github.com/sigstore/gh-action-sigstore-python) from 2.1.0 to 2.1.1. - [Release notes](https://github.com/sigstore/gh-action-sigstore-python/releases) - [Commits](https://github.com/sigstore/gh-action-sigstore-python/compare/v2.1.0...v2.1.1) --- updated-dependencies: - dependency-name: sigstore/gh-action-sigstore-python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7fc17804c..72b002d1e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -47,7 +47,7 @@ jobs: uses: pypa/gh-action-pypi-publish@v1.8.11 - name: sign - uses: sigstore/gh-action-sigstore-python@v2.1.0 + uses: sigstore/gh-action-sigstore-python@v2.1.1 with: inputs: ./dist/*.tar.gz ./dist/*.whl release-signing-artifacts: true From 9bf4d07b04480da90c1f2f023a0dd7d1e8dba21f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 07:50:04 -0600 Subject: [PATCH 40/64] Bump actions/upload-pages-artifact from 2 to 3 (#2294) Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](https://github.com/actions/upload-pages-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4292d5f44..0942afb6d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -37,7 +37,7 @@ jobs: - run: pip install -e ".[doc]" - run: pdoc -o html/ slither '!slither.tools' #TODO fix import errors on pdoc run - name: Upload artifact - uses: actions/upload-pages-artifact@v2 + uses: actions/upload-pages-artifact@v3 with: # Upload the doc path: './html/' From 6620bc926e7d8435256bf9bf0c774c22e0302241 Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:54:04 +0100 Subject: [PATCH 41/64] Fix using for when used with "this" (#2224) --- slither/slithir/convert.py | 23 ++++++++++++++++++ tests/e2e/solc_parsing/test_ast_parsing.py | 1 + ...g-for-this-contract.sol-0.8.15-compact.zip | Bin 0 -> 2745 bytes ...-for-this-contract.sol-0.8.15-compact.json | 8 ++++++ .../test_data/using-for-this-contract.sol | 13 ++++++++++ 5 files changed, 45 insertions(+) create mode 100644 tests/e2e/solc_parsing/test_data/compile/using-for-this-contract.sol-0.8.15-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json create mode 100644 tests/e2e/solc_parsing/test_data/using-for-this-contract.sol diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 4411e3505..170df8cba 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -630,6 +630,17 @@ def propagate_types(ir: Operation, node: "Node"): # pylint: disable=too-many-lo if new_ir: return new_ir + # convert library function when used with "this" + if ( + isinstance(t, ElementaryType) + and t.name == "address" + and ir.destination.name == "this" + and UserDefinedType(node_function.contract) in using_for + ): + new_ir = convert_to_library_or_top_level(ir, node, using_for) + if new_ir: + return new_ir + if isinstance(t, UserDefinedType): # UserdefinedType t_type = t.type @@ -1564,6 +1575,18 @@ def convert_to_library_or_top_level( if new_ir: return new_ir + if ( + isinstance(t, ElementaryType) + and t.name == "address" + and ir.destination.name == "this" + and UserDefinedType(node.function.contract) in using_for + ): + new_ir = look_for_library_or_top_level( + contract, ir, using_for, UserDefinedType(node.function.contract) + ) + if new_ir: + return new_ir + return None diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index bc57dc51b..e233fa993 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -448,6 +448,7 @@ ALL_TESTS = [ Test("using-for-functions-list-3-0.8.0.sol", ["0.8.15"]), Test("using-for-functions-list-4-0.8.0.sol", ["0.8.15"]), Test("using-for-global-0.8.0.sol", ["0.8.15"]), + Test("using-for-this-contract.sol", ["0.8.15"]), Test("library_event-0.8.16.sol", ["0.8.16"]), Test("top-level-struct-0.8.0.sol", ["0.8.0"]), Test("yul-top-level-0.8.0.sol", ["0.8.0"]), diff --git a/tests/e2e/solc_parsing/test_data/compile/using-for-this-contract.sol-0.8.15-compact.zip b/tests/e2e/solc_parsing/test_data/compile/using-for-this-contract.sol-0.8.15-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..6950666a479e8b3c138633675a65c8f101cd0069 GIT binary patch literal 2745 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 literal 0 HcmV?d00001 diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json new file mode 100644 index 000000000..43eca2c9a --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json @@ -0,0 +1,8 @@ +{ + "Lib": { + "f(Hello)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" + }, + "Hello": { + "test()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/using-for-this-contract.sol b/tests/e2e/solc_parsing/test_data/using-for-this-contract.sol new file mode 100644 index 000000000..33bbc74cd --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/using-for-this-contract.sol @@ -0,0 +1,13 @@ +library Lib { + function f(Hello h) external { + + } +} +contract Hello { + using Lib for Hello; + + function test() external { + this.f(); + } +} + From 4f09d238236c971602a00ef8a9e7992f243ba7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Wed, 7 Feb 2024 18:02:15 -0300 Subject: [PATCH 42/64] Make triage database path customizable --- slither/__main__.py | 10 +++++++++- slither/slither.py | 2 ++ slither/utils/command_line.py | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/slither/__main__.py b/slither/__main__.py index d1b36d951..3cd914a87 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -528,12 +528,20 @@ def parse_args( group_misc.add_argument( "--triage-mode", - help="Run triage mode (save results in slither.db.json)", + help="Run triage mode (save results in triage database)", action="store_true", dest="triage_mode", default=False, ) + group_misc.add_argument( + "--triage-database", + help="File path to the triage database (default: slither.db.json)", + action="store", + dest="triage_database", + default=defaults_flag_in_config["triage_database"], + ) + group_misc.add_argument( "--config-file", help="Provide a config file (default: slither.config.json)", diff --git a/slither/slither.py b/slither/slither.py index 747d2207e..a3cc64404 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -135,7 +135,9 @@ class Slither( self._exclude_dependencies = kwargs.get("exclude_dependencies", False) triage_mode = kwargs.get("triage_mode", False) + triage_database = kwargs.get("triage_database", "slither.db.json") self._triage_mode = triage_mode + self._previous_results_filename = triage_database printers_to_run = kwargs.get("printers_to_run", "") if printers_to_run == "echidna": diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index 6c50fcab9..2432a2116 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -70,6 +70,7 @@ defaults_flag_in_config = { "no_fail": False, "sarif_input": "export.sarif", "sarif_triage": "export.sarif.sarifexplorer", + "triage_database": "slither.db.json", **DEFAULTS_FLAG_IN_CONFIG_CRYTIC_COMPILE, } From e876d61fd51fac747fd22f906026037161f7d24f Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Thu, 8 Feb 2024 13:27:50 -0800 Subject: [PATCH 43/64] fix: broken doc links (#2299) * fix: broken doc links * style: black --- README.md | 6 +++--- slither/detectors/assembly/incorrect_return.py | 4 +++- slither/detectors/assembly/return_instead_of_leave.py | 2 +- tests/e2e/compilation/test_resolution.py | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 37f678d7a..769ac58aa 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Slither - Read the Docs](https://img.shields.io/badge/Slither-Read_the_Docs-2ea44f)](https://crytic.github.io/slither/slither.html) [![Slither - Wiki](https://img.shields.io/badge/Slither-Wiki-2ea44f)](https://github.com/crytic/slither/wiki/SlithIR) -> Join the Empire Hacking Slack +> Join the Empire Hacking Slack > > [![Slack Status](https://slack.empirehacking.nyc/badge.svg)](https://slack.empirehacking.nyc/) > > - Discussions and Support @@ -131,10 +131,10 @@ Num | Detector | What it Detects | Impact | Confidence 20 | `controlled-delegatecall` | [Controlled delegatecall destination](https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall) | High | Medium 21 | `delegatecall-loop` | [Payable functions using `delegatecall` inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop) | High | Medium 22 | `incorrect-exp` | [Incorrect exponentiation](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-exponentiation) | High | Medium -23 | `incorrect-return` | [If a `return` is incorrectly used in assembly mode.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return) | High | Medium +23 | `incorrect-return` | [If a `return` is incorrectly used in assembly mode.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-return-in-assembly) | High | Medium 24 | `msg-value-loop` | [msg.value inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop) | High | Medium 25 | `reentrancy-eth` | [Reentrancy vulnerabilities (theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities) | High | Medium -26 | `return-leave` | [If a `return` is used instead of a `leave`.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return) | High | Medium +26 | `return-leave` | [If a `return` is used instead of a `leave`.](https://github.com/crytic/slither/wiki/Detector-Documentation#return-instead-of-leave-in-assembly) | High | Medium 27 | `storage-array` | [Signed storage integer array compiler bug](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array) | High | Medium 28 | `unchecked-transfer` | [Unchecked tokens transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer) | High | Medium 29 | `weak-prng` | [Weak PRNG](https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG) | High | Medium diff --git a/slither/detectors/assembly/incorrect_return.py b/slither/detectors/assembly/incorrect_return.py index f5f0a98d9..bd5a6d844 100644 --- a/slither/detectors/assembly/incorrect_return.py +++ b/slither/detectors/assembly/incorrect_return.py @@ -39,7 +39,9 @@ class IncorrectReturn(AbstractDetector): IMPACT = DetectorClassification.HIGH CONFIDENCE = DetectorClassification.MEDIUM - WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return" + WIKI = ( + "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-return-in-assembly" + ) WIKI_TITLE = "Incorrect return in assembly" WIKI_DESCRIPTION = "Detect if `return` in an assembly block halts unexpectedly the execution." diff --git a/slither/detectors/assembly/return_instead_of_leave.py b/slither/detectors/assembly/return_instead_of_leave.py index a1591d834..a1ad9c87e 100644 --- a/slither/detectors/assembly/return_instead_of_leave.py +++ b/slither/detectors/assembly/return_instead_of_leave.py @@ -20,7 +20,7 @@ class ReturnInsteadOfLeave(AbstractDetector): IMPACT = DetectorClassification.HIGH CONFIDENCE = DetectorClassification.MEDIUM - WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return" + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#return-instead-of-leave-in-assembly" WIKI_TITLE = "Return instead of leave in assembly" WIKI_DESCRIPTION = "Detect if a `return` is used where a `leave` should be used." diff --git a/tests/e2e/compilation/test_resolution.py b/tests/e2e/compilation/test_resolution.py index af7cbe2c7..c3290624b 100644 --- a/tests/e2e/compilation/test_resolution.py +++ b/tests/e2e/compilation/test_resolution.py @@ -57,6 +57,6 @@ def test_contract_function_parameter(solc_binary_path) -> None: function = contract.functions[0] parameters = function.parameters - assert (parameters[0].name == 'param1') - assert (parameters[1].name == '') - assert (parameters[2].name == 'param3') + assert parameters[0].name == "param1" + assert parameters[1].name == "" + assert parameters[2].name == "param3" From 247a90edbc94aa512232f3c32e675d8a7e71f265 Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Tue, 13 Feb 2024 19:03:25 +0400 Subject: [PATCH 44/64] fixed immediate inheritance --- slither/solc_parsing/slither_compilation_unit_solc.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 85921ce74..de8725b94 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -456,9 +456,12 @@ Please rename it, this name is reserved for Slither's internals""" # Resolve immediate base contracts for i in contract_parser.baseContracts: if i in contract_parser.remapping: + contract_name = contract_parser.remapping[i] + if contract_name in contract_parser.underlying_contract.file_scope.renaming: + contract_name = contract_parser.underlying_contract.file_scope.renaming[contract_name] fathers.append( contract_parser.underlying_contract.file_scope.get_contract_from_name( - contract_parser.remapping[i] + contract_name ) # self._compilation_unit.get_contract_from_name(contract_parser.remapping[i]) ) From 50f1b98b94f962db6a6b3e6d788b6a1df2834215 Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Tue, 13 Feb 2024 19:16:15 +0400 Subject: [PATCH 45/64] reformatted --- slither/solc_parsing/slither_compilation_unit_solc.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index de8725b94..21dbfff70 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -458,7 +458,9 @@ Please rename it, this name is reserved for Slither's internals""" if i in contract_parser.remapping: contract_name = contract_parser.remapping[i] if contract_name in contract_parser.underlying_contract.file_scope.renaming: - contract_name = contract_parser.underlying_contract.file_scope.renaming[contract_name] + contract_name = contract_parser.underlying_contract.file_scope.renaming[ + contract_name + ] fathers.append( contract_parser.underlying_contract.file_scope.get_contract_from_name( contract_name From 9fd6128b94ef041b8c780ef9aa550693b2ebcec0 Mon Sep 17 00:00:00 2001 From: unknown <951161604@qq.com> Date: Thu, 15 Feb 2024 23:18:28 +0800 Subject: [PATCH 46/64] Changes to be committed: modified: examples/scripts/possible_paths.py --- examples/scripts/possible_paths.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/scripts/possible_paths.py b/examples/scripts/possible_paths.py index 06b68c2bc..6f83e13f0 100644 --- a/examples/scripts/possible_paths.py +++ b/examples/scripts/possible_paths.py @@ -19,7 +19,7 @@ def resolve_function(contract_name, function_name): contract = contracts[0] # Obtain the target function target_function = next( - (function for function in contract.functions if function.name == function_name), None + (function for function in contract.functions_declared if function.name == function_name), None ) # Verify we have resolved the function specified. From b66b3e091f3352c975937972f767ff5ee86f3fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 16 Feb 2024 16:26:28 -0300 Subject: [PATCH 47/64] slither: utils: respect colorization state when printing tables Closes #2229 --- slither/utils/myprettytable.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index d67f570c0..b33fb9c5f 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -1,7 +1,10 @@ from typing import List, Dict, Union +from prettytable import PrettyTable from prettytable.colortable import ColorTable, Themes +from slither.utils.colors import Colors + class MyPrettyTable: def __init__(self, field_names: List[str], pretty_align: bool = True): # TODO: True by default? @@ -19,8 +22,12 @@ class MyPrettyTable: def add_row(self, row: List[Union[str, List[str]]]) -> None: self._rows.append(row) - def to_pretty_table(self) -> ColorTable: - table = ColorTable(self._field_names, theme=Themes.OCEAN) + def to_pretty_table(self) -> PrettyTable: + if Colors.COLORIZATION_ENABLED: + table = ColorTable(self._field_names, theme=Themes.OCEAN) + else: + table = PrettyTable(self._field_names) + for row in self._rows: table.add_row(row) if len(self._options["set_alignment"]): From 3eebf49c1a3ec54c74ddeb1662df1ae6f9ddb05e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 22:41:00 +0000 Subject: [PATCH 48/64] Bump actions/download-artifact from 3 to 4 Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/publish.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 72b002d1e..234e2eb05 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -38,7 +38,7 @@ jobs: - build-release steps: - name: fetch dists - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: slither-dists path: dist/ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 68a32f80a..d67721841 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -109,7 +109,7 @@ jobs: - run: pip install coverage[toml] - name: download coverage data - uses: actions/download-artifact@v3.0.2 + uses: actions/download-artifact@v4 with: name: coverage-data From b107e9e22cd79acce47c02a4aab70144e2e0186a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 16 Feb 2024 16:37:30 -0300 Subject: [PATCH 49/64] Bump actions/upload-artifact from 3 to 4 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... --- .github/actions/upload-coverage/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/upload-coverage/action.yml b/.github/actions/upload-coverage/action.yml index ac620c8e6..789509080 100644 --- a/.github/actions/upload-coverage/action.yml +++ b/.github/actions/upload-coverage/action.yml @@ -21,7 +21,7 @@ runs: fi id: coverage-uuid shell: bash - - uses: actions/upload-artifact@v3.1.0 + - uses: actions/upload-artifact@v4 with: name: coverage-data path: | From 4a6920a2b5cfcce5b9f643e96e30280081e3028d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 16 Feb 2024 16:41:47 -0300 Subject: [PATCH 50/64] ci: test: adjust to new artifact merging behavior --- .github/actions/upload-coverage/action.yml | 4 ++-- .github/workflows/test.yml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/actions/upload-coverage/action.yml b/.github/actions/upload-coverage/action.yml index 789509080..02fb82f65 100644 --- a/.github/actions/upload-coverage/action.yml +++ b/.github/actions/upload-coverage/action.yml @@ -15,7 +15,7 @@ runs: # This method has the limitation of 1 coverage file per run, limiting some coverage between online/offline tests. - run: | COVERAGE_UUID=$(python3 -c "import uuid; print(uuid.uuid4())") - echo "COVERAGE_UUID=${COVERAGE_UUID}" >> $GITHUB_OUTPUT + echo "COVERAGE_UUID=${COVERAGE_UUID}" >> "$GITHUB_OUTPUT" if [ -f .coverage ]; then mv .coverage .coverage.${COVERAGE_UUID} fi @@ -23,7 +23,7 @@ runs: shell: bash - uses: actions/upload-artifact@v4 with: - name: coverage-data + name: coverage-data-${{ steps.coverage-uuid.outputs.COVERAGE_UUID }} path: | .coverage.* *.lcov diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d67721841..f91243cc7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -111,7 +111,8 @@ jobs: - name: download coverage data uses: actions/download-artifact@v4 with: - name: coverage-data + pattern: coverage-data-* + merge-multiple: true - name: combine coverage data id: combinecoverage From 261182f34061caefe032170fa8ad6a42522f3d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 16 Feb 2024 21:44:01 -0300 Subject: [PATCH 51/64] tools: properties: correct tool description and usage Closes #568 --- slither/tools/properties/__main__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/slither/tools/properties/__main__.py b/slither/tools/properties/__main__.py index 10837bb4b..b5e5c911a 100644 --- a/slither/tools/properties/__main__.py +++ b/slither/tools/properties/__main__.py @@ -68,13 +68,13 @@ def parse_args() -> argparse.Namespace: :return: Returns the arguments for the program. """ parser = argparse.ArgumentParser( - description="Demo", - usage="slither-demo filename", + description="Generates code properties (e.g., invariants) that can be tested with unit tests or Echidna, entirely automatically.", + usage="slither-prop filename", formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument( - "filename", help="The filename of the contract or truffle directory to analyze." + "filename", help="The filename of the contract or project directory to analyze." ) parser.add_argument("--contract", help="The targeted contract.") From 9996e4e56e2dbe7273bf213f28b56cbd9bf20397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 16 Feb 2024 22:03:49 -0300 Subject: [PATCH 52/64] tools: documentation: correct tool description --- slither/tools/documentation/__main__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/slither/tools/documentation/__main__.py b/slither/tools/documentation/__main__.py index 39b1eacda..0244dd6c6 100644 --- a/slither/tools/documentation/__main__.py +++ b/slither/tools/documentation/__main__.py @@ -21,7 +21,10 @@ def parse_args() -> argparse.Namespace: Parse the underlying arguments for the program. :return: Returns the arguments for the program. """ - parser = argparse.ArgumentParser(description="Demo", usage="slither-documentation filename") + parser = argparse.ArgumentParser( + description="Auto-generate NatSpec documentation for every function using OpenAI Codex.", + usage="slither-documentation filename", + ) parser.add_argument("project", help="The target directory/Solidity file.") From f2f7598ccf2559a64ae8dd8f79ced7ae9e174c3d Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Sat, 17 Feb 2024 09:05:15 -0600 Subject: [PATCH 53/64] fmt --- examples/scripts/possible_paths.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/scripts/possible_paths.py b/examples/scripts/possible_paths.py index 6f83e13f0..2057782a4 100644 --- a/examples/scripts/possible_paths.py +++ b/examples/scripts/possible_paths.py @@ -19,7 +19,8 @@ def resolve_function(contract_name, function_name): contract = contracts[0] # Obtain the target function target_function = next( - (function for function in contract.functions_declared if function.name == function_name), None + (function for function in contract.functions_declared if function.name == function_name), + None, ) # Verify we have resolved the function specified. From 4f4acae1af3e4c68555972ea09afe686427d20db Mon Sep 17 00:00:00 2001 From: Judy Wu Date: Sun, 18 Feb 2024 14:39:58 -0500 Subject: [PATCH 54/64] feat: address issue #1644 and add new api to return state variables that have a storage location instead of filtering --- slither/core/compilation_unit.py | 5 +--- slither/core/declarations/contract.py | 27 +++++++++++++++++++ slither/core/variables/variable.py | 7 +++++ .../variables/unchanged_state_variables.py | 4 +-- slither/printers/summary/variable_order.py | 7 +++-- slither/tools/read_storage/read_storage.py | 2 +- .../checks/variable_initialization.py | 4 +-- .../upgradeability/checks/variables_order.py | 24 +++-------------- slither/utils/encoding.py | 2 +- slither/utils/upgradeability.py | 20 +++++--------- 10 files changed, 54 insertions(+), 48 deletions(-) diff --git a/slither/core/compilation_unit.py b/slither/core/compilation_unit.py index 6221fd8bd..df652dab0 100644 --- a/slither/core/compilation_unit.py +++ b/slither/core/compilation_unit.py @@ -302,10 +302,7 @@ class SlitherCompilationUnit(Context): slot = 0 offset = 0 - for var in contract.state_variables_ordered: - if var.is_constant or var.is_immutable: - continue - + for var in contract.stored_state_variables_ordered: assert var.type size, new_slot = var.type.storage_size diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 5403d227a..7224859c6 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -436,6 +436,33 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods """ return list(self._variables.values()) + @property + def stored_state_variables(self) -> List["StateVariable"]: + """ + Returns state variables with storage locations, excluding private variables from inherited contracts. + Use stored_state_variables_ordered to access variables with storage locations in their declaration order. + + This implementation filters out state variables if they are constant or immutable. It will be + updated to accommodate any new non-storage keywords that might replace 'constant' and 'immutable' in the future. + + Returns: + List[StateVariable]: A list of state variables with storage locations. + """ + return [variable for variable in self.state_variables if variable.is_stored] + + @property + def stored_state_variables_ordered(self) -> List["StateVariable"]: + """ + list(StateVariable): List of the state variables with storage locations by order of declaration. + + This implementation filters out state variables if they are constant or immutable. It will be + updated to accommodate any new non-storage keywords that might replace 'constant' and 'immutable' in the future. + + Returns: + List[StateVariable]: A list of state variables with storage locations ordered by declaration. + """ + return [variable for variable in self.state_variables_ordered if variable.is_stored] + @property def state_variables_entry_points(self) -> List["StateVariable"]: """ diff --git a/slither/core/variables/variable.py b/slither/core/variables/variable.py index f9ef19024..63d1a7a83 100644 --- a/slither/core/variables/variable.py +++ b/slither/core/variables/variable.py @@ -93,6 +93,13 @@ class Variable(SourceMapping): def is_constant(self, is_cst: bool) -> None: self._is_constant = is_cst + @property + def is_stored(self) -> bool: + """ + Checks if a variable is stored, based on it not being constant or immutable. Future updates may adjust for new non-storage keywords. + """ + return not self._is_constant and not self._is_immutable + @property def is_reentrant(self) -> bool: return self._is_reentrant diff --git a/slither/detectors/variables/unchanged_state_variables.py b/slither/detectors/variables/unchanged_state_variables.py index 0e73ab57b..5771d9630 100644 --- a/slither/detectors/variables/unchanged_state_variables.py +++ b/slither/detectors/variables/unchanged_state_variables.py @@ -25,7 +25,7 @@ def _is_valid_type(v: StateVariable) -> bool: def _valid_candidate(v: StateVariable) -> bool: - return _is_valid_type(v) and not (v.is_constant or v.is_immutable) + return _is_valid_type(v) def _is_constant_var(v: Variable) -> bool: @@ -92,7 +92,7 @@ class UnchangedStateVariables: variables = [] functions = [] - variables.append(c.state_variables) + variables.append(c.stored_state_variables) functions.append(c.all_functions_called) valid_candidates: Set[StateVariable] = { diff --git a/slither/printers/summary/variable_order.py b/slither/printers/summary/variable_order.py index 3325b7a01..0d8ce2612 100644 --- a/slither/printers/summary/variable_order.py +++ b/slither/printers/summary/variable_order.py @@ -28,10 +28,9 @@ class VariableOrder(AbstractPrinter): for contract in self.slither.contracts_derived: txt += f"\n{contract.name}:\n" table = MyPrettyTable(["Name", "Type", "Slot", "Offset"]) - for variable in contract.state_variables_ordered: - if not variable.is_constant and not variable.is_immutable: - slot, offset = contract.compilation_unit.storage_layout_of(contract, variable) - table.add_row([variable.canonical_name, str(variable.type), slot, offset]) + for variable in contract.stored_state_variables_ordered: + slot, offset = contract.compilation_unit.storage_layout_of(contract, variable) + table.add_row([variable.canonical_name, str(variable.type), slot, offset]) all_tables.append((contract.name, table)) txt += str(table) + "\n" diff --git a/slither/tools/read_storage/read_storage.py b/slither/tools/read_storage/read_storage.py index 8c0cf515d..728636f2e 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -398,7 +398,7 @@ class SlitherReadStorage: for contract in self.contracts: for var in contract.state_variables_ordered: if func(var): - if not var.is_constant and not var.is_immutable: + if var.is_stored: self._target_variables.append((contract, var)) elif ( self.unstructured diff --git a/slither/tools/upgradeability/checks/variable_initialization.py b/slither/tools/upgradeability/checks/variable_initialization.py index b4535ddfe..b86036c87 100644 --- a/slither/tools/upgradeability/checks/variable_initialization.py +++ b/slither/tools/upgradeability/checks/variable_initialization.py @@ -43,8 +43,8 @@ Using initialize functions to write initial values in state variables. def _check(self) -> List[Output]: results = [] - for s in self.contract.state_variables_ordered: - if s.initialized and not (s.is_constant or s.is_immutable): + for s in self.contract.stored_state_variables_ordered: + if s.initialized: info: CHECK_INFO = [s, " is a state variable with an initial value.\n"] json = self.generate_result(info) results.append(json) diff --git a/slither/tools/upgradeability/checks/variables_order.py b/slither/tools/upgradeability/checks/variables_order.py index 002559b6e..fce0a09bb 100644 --- a/slither/tools/upgradeability/checks/variables_order.py +++ b/slither/tools/upgradeability/checks/variables_order.py @@ -115,16 +115,8 @@ Avoid variables in the proxy. If a variable is in the proxy, ensure it has the s def _check(self) -> List[Output]: contract1 = self._contract1() contract2 = self._contract2() - order1 = [ - variable - for variable in contract1.state_variables_ordered - if not (variable.is_constant or variable.is_immutable) - ] - order2 = [ - variable - for variable in contract2.state_variables_ordered - if not (variable.is_constant or variable.is_immutable) - ] + order1 = [variable for variable in contract1.stored_state_variables_ordered] + order2 = [variable for variable in contract2.stored_state_variables_ordered] results: List[Output] = [] for idx, _ in enumerate(order1): @@ -244,16 +236,8 @@ Avoid variables in the proxy. If a variable is in the proxy, ensure it has the s def _check(self) -> List[Output]: contract1 = self._contract1() contract2 = self._contract2() - order1 = [ - variable - for variable in contract1.state_variables_ordered - if not (variable.is_constant or variable.is_immutable) - ] - order2 = [ - variable - for variable in contract2.state_variables_ordered - if not (variable.is_constant or variable.is_immutable) - ] + order1 = [variable for variable in contract1.stored_state_variables_ordered] + order2 = [variable for variable in contract2.stored_state_variables_ordered] results = [] diff --git a/slither/utils/encoding.py b/slither/utils/encoding.py index 288b58150..86e26cdbe 100644 --- a/slither/utils/encoding.py +++ b/slither/utils/encoding.py @@ -71,7 +71,7 @@ def encode_var_for_compare(var: Union[variables.Variable, SolidityVariable]) -> if isinstance(var, variables.LocalVariable): return f"local_solc_variable({ntype(var.type)},{var.location})" if isinstance(var, variables.StateVariable): - if not (var.is_constant or var.is_immutable): + if var.is_stored: try: slot, _ = var.contract.compilation_unit.storage_layout_of(var.contract, var) except KeyError: diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index bbb253175..e8300ba84 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -81,12 +81,8 @@ def compare( tainted-contracts: list[TaintedExternalContract] """ - order_vars1 = [ - v for v in v1.state_variables_ordered if not v.is_constant and not v.is_immutable - ] - order_vars2 = [ - v for v in v2.state_variables_ordered if not v.is_constant and not v.is_immutable - ] + order_vars1 = [v for v in v1.stored_state_variables_ordered] + order_vars2 = [v for v in v2.stored_state_variables_ordered] func_sigs1 = [function.solidity_signature for function in v1.functions] func_sigs2 = [function.solidity_signature for function in v2.functions] @@ -206,7 +202,7 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon elif ( isinstance(target, StateVariable) and target not in (v for v in tainted_contracts[contract.name].tainted_variables) - and not (target.is_constant or target.is_immutable) + and target.is_stored ): # Found a new high-level call to a public state variable getter tainted_contracts[contract.name].add_tainted_variable(target) @@ -304,12 +300,8 @@ def get_missing_vars(v1: Contract, v2: Contract) -> List[StateVariable]: List of StateVariables from v1 missing in v2 """ results = [] - order_vars1 = [ - v for v in v1.state_variables_ordered if not v.is_constant and not v.is_immutable - ] - order_vars2 = [ - v for v in v2.state_variables_ordered if not v.is_constant and not v.is_immutable - ] + order_vars1 = [v for v in v1.stored_state_variables_ordered] + order_vars2 = [v for v in v2.stored_state_variables_ordered] if len(order_vars2) < len(order_vars1): for variable in order_vars1: if variable.name not in [v.name for v in order_vars2]: @@ -366,7 +358,7 @@ def get_proxy_implementation_slot(proxy: Contract) -> Optional[SlotInfo]: delegate = get_proxy_implementation_var(proxy) if isinstance(delegate, StateVariable): - if not delegate.is_constant and not delegate.is_immutable: + if delegate.is_stored: srs = SlitherReadStorage([proxy], 20) return srs.get_storage_slot(delegate, proxy) if delegate.is_constant and delegate.type.name == "bytes32": From 591c4c09530dd22e6cb246b43ea3c6232bbac00a Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 19 Feb 2024 14:39:25 +0100 Subject: [PATCH 55/64] Add test --- tests/e2e/solc_parsing/test_ast_parsing.py | 23 +++++++++++----- .../solidity-0.8.24.sol-0.8.24-compact.zip | Bin 0 -> 2684 bytes .../solidity-0.8.24.sol-0.8.24-compact.json | 6 ++++ .../test_data/solidity-0.8.24.sol | 26 ++++++++++++++++++ 4 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 tests/e2e/solc_parsing/test_data/compile/solidity-0.8.24.sol-0.8.24-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/expected/solidity-0.8.24.sol-0.8.24-compact.json create mode 100644 tests/e2e/solc_parsing/test_data/solidity-0.8.24.sol diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index bc57dc51b..18793d54d 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -21,12 +21,18 @@ TEST_ROOT = os.path.join(E2E_ROOT, "solc_parsing", "test_data") # pylint: disable=too-few-public-methods class Test: - def __init__(self, test_file: str, solc_versions: List[str], disable_legacy: bool = False): + def __init__( + self, + test_file: str, + solc_versions: List[str], + disable_legacy: bool = False, + solc_args: str = None, + ): self.solc_versions = solc_versions self.test_file = test_file self.disable_legacy = disable_legacy - versions_with_flavors: List[Tuple[str, str]] = [] + versions_with_flavors: List[Tuple[str, str, str]] = [] flavors = ["compact"] if not self.disable_legacy: flavors += ["legacy"] @@ -42,7 +48,7 @@ class Test: ) < parse_version("0.4.12") if legacy_unavailable or compact_unavailable: continue - versions_with_flavors.append((version, flavor)) + versions_with_flavors.append((version, flavor, solc_args)) self.versions_with_flavors = versions_with_flavors @@ -462,6 +468,7 @@ ALL_TESTS = [ Test("aliasing/main.sol", ["0.8.19"]), Test("type-aliases.sol", ["0.8.19"]), Test("enum-max-min.sol", ["0.8.19"]), + Test("solidity-0.8.24.sol", ["0.8.24"], solc_args="--evm-version cancun"), ] # create the output folder if needed try: @@ -473,7 +480,7 @@ except OSError: def pytest_generate_tests(metafunc): test_cases = [] for test_item in ALL_TESTS: - for version, flavor in test_item.versions_with_flavors: + for version, flavor, _ in test_item.versions_with_flavors: test_cases.append((test_item.test_file, version, flavor)) metafunc.parametrize("test_file, version, flavor", test_cases) @@ -537,7 +544,7 @@ def _generate_test(test_item: Test, skip_existing=False): flavors = ["compact"] if not test_item.disable_legacy: flavors += ["legacy"] - for version, flavor in test_item.versions_with_flavors: + for version, flavor, _ in test_item.versions_with_flavors: test_file = os.path.join( TEST_ROOT, "compile", f"{test_item.test_file}-{version}-{flavor}.zip" ) @@ -582,7 +589,7 @@ def set_solc(version: str): def _generate_compile(test_item: Test, skip_existing=False): - for version, flavor in test_item.versions_with_flavors: + for version, flavor, solc_args in test_item.versions_with_flavors: test_file = os.path.join(TEST_ROOT, test_item.test_file) expected_file = os.path.join( TEST_ROOT, "compile", f"{test_item.test_file}-{version}-{flavor}.zip" @@ -594,7 +601,9 @@ def _generate_compile(test_item: Test, skip_existing=False): set_solc(version) print(f"Compiled to {expected_file}") - cc = CryticCompile(test_file, solc_force_legacy_json=flavor == "legacy") + cc = CryticCompile( + test_file, solc_force_legacy_json=flavor == "legacy", solc_args=solc_args + ) # pylint: disable=no-member Path(expected_file).parents[0].mkdir(parents=True, exist_ok=True) diff --git a/tests/e2e/solc_parsing/test_data/compile/solidity-0.8.24.sol-0.8.24-compact.zip b/tests/e2e/solc_parsing/test_data/compile/solidity-0.8.24.sol-0.8.24-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..40e94f3565f86c18d7d285d44d821ff92a826ec6 GIT binary patch literal 2684 zcma);`8yMi1ILHC3h^PgsQ1l)2wzZO7$%4t$PVxT0I&dnAr9xS z@mnLLczB>upO@4f6rj+4CMn%f+(>#XtW8*rVQ!Q$DRD!9zSz8V()DpB!&>}TE!c6L zm}_0eKmH{=q%er zTmKu_xBDi~zW8u9#f1j9_`4;GGcORPZ@5q8B%TY&s8`;O$v=9Z+lD_(|5a8)>EZ2m zM>6XIL|Ql~6QfLHf3DV_;QGNX@=)fzCENH+aHD(5XR75#nxXYJ$CjQ`%J-`h-v>IKC|I5IuZ&>X)TJ zx~EWYuEN_(;<#PQx#qQ{hoT}?7r)1%%vxd;kyFnrjdK;A85t2i#9^HHH}udAN46hUX@F-7*yn~xL9jT@Yp6BuQZleutG#tntfBEjnvl;v^#_TE~mJ{n)YkEkHxxi9l z@Tos=MR5SJB8V3GewWo0$oK#oY7=i;>3fA^R2vjYq)-g3fhPXab|1Tzn-EJmg-#H@ zCDeXC6f0P)#?Glsxi!g>b+`_zF4n3%Gxy-Q;P9u#llJ+OIJw$+7WS1WJ?-}z0k|xH z$QD2HZDACpa?_%~=#;%_f6J1P2Q*Y%G&M_1(n z5@f5CUg~49v?%$cF4J{_`-iOeIeRe2keWc!wC|3E&g+L~*q%Mo=}B8&c|e1q(yB*d zmY}m1|4cS zB!{G3I+r$B0=L(!)L8T71n+L^ozwLARMCB9^G&5cAp@L{U9WPcm4BXk`^HhmAW;zE zsLKZs+keEu#!%!21$;0S2w@$bb+ zy|d@&DZK?UJk;-8xig#3EWCXxj@mz@)3|kPRlM4@wOgG&>r0s4?|&_F~tmBt&i>>Dm zHy8BcTU4FT-y&q%T-|dQ8=|s({wmYxI$DyvwishBE@hkWXh2(EC=v&*&7kM;5FTN$ zPa2Y|P83)F>chNnqRp`55p5c+X{iK$KOtcR=VgU??%6 zS&LRi(_hSxY|ukBa4KxPL1$M5$s(tAaFL5yPeAcTJbw;X#B$Mh# zM2>VfE_@#K$tNvQnnU+jq6dwc_U1;z`kldHkI;wm;eCs1TC#()Jizhn6+O||mhfrU zMho$B%lUS`4O54AkbtQ>5lpA1Dlc60ZkK?#2m0N7n!q&`gRR9G5CfozVR@6Fe1sVB zba@qjXmY2a&e^Gg;QfBMawAqm>M0!ZG}uJzDkJ(PIUrV&bkE!GpjJZ8y$<~}t?i0h zJRbD!cq_SC7Y8W2-|Ya2A|;A8Gnfgh(`iW0S=#Fx2h4S>kP)Fmrj0EX;Ij=}FkE^wWA6&$8uu#V%Hup=gC(&Y{6#KC_%f+Ui zo&}bX00o6?h7APe&1dkJvBy51^zhjOr8?6sv=i(ePRIXFVyw!J?@w5 zMRlL)lzlMO&!3deLne=iB%V@-_Pr3j4yP1Vrr+U}*Xz}ejo@7(VHNM{-*{1L#Gx%nKYSi?(LjH%v(?fN(y8g6=zQ5})b58>5oT>Z z2ui)sbnrZ&ruSI&S9Z3UNthHqLM}0C31+26Jm|vjA@^(DkUn>2o4$`>1h|tlHGtV+ zJUq!fnv9HZo$UzH00UmD>ex3SRmtXr-t?hP+rd-fJL1j z4pZcQXk@%Cp$q3kbc~+m?(xlBWlZ$Dq6rYM*~AykU4;)dS8)V28HE})V5`a$jKeZT z`FRcZO(VVN?^_%zJ{$H$VY=z3E%xJz5{xHX5mbt?ls$?+tQax|x1G9=+CImw1 zlE1o1Bd~%896|;>PQ1OKK(grRj)xDmsoXvCrLTcW~AIM@C$^ z@q{4ieFw=rEP^zt&KYXXC5gB$>z$7H44POlhKF_ez6(49C^A%{t`nss`K_POOlVooDLbNaGA$NPdK>TVbkCEaz3ve9wMMTz6;`=F^~0ePz?D1ytgbI zn4BkgR>)tPA<1304SPm5A^X`Nxr>bifZ(4;$j3<5UXR*m5m;Mf?H8p-tpq+Mpk-nl za9unGbN-TSlAIc2F0+x>CV^EH{aWHv>1E5{*>z`umi}XzD@Xto!oq6I_P>?zj}`tm aSeC!@e+nWL!p`yc&hn=&e^%hcU-}Q+iwXY# literal 0 HcmV?d00001 diff --git a/tests/e2e/solc_parsing/test_data/expected/solidity-0.8.24.sol-0.8.24-compact.json b/tests/e2e/solc_parsing/test_data/expected/solidity-0.8.24.sol-0.8.24-compact.json new file mode 100644 index 000000000..be308dd12 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/solidity-0.8.24.sol-0.8.24-compact.json @@ -0,0 +1,6 @@ +{ + "A": { + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->12;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: END INLINE ASM 11\n\"];\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->1;\n}\n", + "NonReentrant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: IF 2\n\"];\n2->4[label=\"True\"];\n2->3[label=\"False\"];\n3[label=\"Node Type: END_IF 3\n\"];\n3->5;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END INLINE ASM 6\n\"];\n6->7;\n7[label=\"Node Type: _ 7\n\"];\n7->8;\n8[label=\"Node Type: INLINE ASM 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: END INLINE ASM 10\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/solidity-0.8.24.sol b/tests/e2e/solc_parsing/test_data/solidity-0.8.24.sol new file mode 100644 index 000000000..eb96f5d28 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/solidity-0.8.24.sol @@ -0,0 +1,26 @@ +contract A { + + modifier NonReentrant { + assembly { + if tload(0) { revert(0, 0) } + tstore(0, 1) + } + _; + assembly { + tstore(0, 0) + } + } + + function a() NonReentrant public { + bytes32 _blobhash = blobhash(2); + uint _blobbasefee = block.blobbasefee; + + assembly { + let __blobbasefee := blobbasefee() + let _basefee := basefee() + let __blobhash := blobhash(3) + mcopy(0, 0x40, 0x20) + } + } +} + From fda9935c5236c3eee1e63a7c1d52c83f58d933c3 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 19 Feb 2024 17:23:23 +0100 Subject: [PATCH 56/64] Add ENDASSEMLBY node for solc < 0.6.0 --- slither/solc_parsing/declarations/function.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index c1b94661d..5698f7b26 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -996,7 +996,9 @@ class FunctionSolc(CallerContextExpression): if "operations" in statement: asm_node.underlying_node.add_inline_asm(statement["operations"]) link_underlying_nodes(node, asm_node) - node = asm_node + end_assembly = self._new_node(NodeType.ENDASSEMBLY, statement["src"], scope) + link_underlying_nodes(asm_node, end_assembly) + node = end_assembly elif name == "DoWhileStatement": node = self._parse_dowhile(statement, node, scope) # For Continue / Break / Return / Throw From f57c2ca0b3ff45f449f48a198516c1cbfb14b36e Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 19 Feb 2024 17:24:37 +0100 Subject: [PATCH 57/64] Detect only assembly blocks --- shift_parameter_mixup.sol | 11 +++++++++++ .../assembly/shift_parameter_mixup.py | 11 +++++++++++ ...up_0_6_11_shift_parameter_mixup_sol__0.txt | 2 +- ...xup_0_7_6_shift_parameter_mixup_sol__0.txt | 2 +- .../0.4.25/shift_parameter_mixup.sol | 5 ++++- .../shift_parameter_mixup.sol-0.4.25.zip | Bin 1387 -> 1765 bytes .../0.5.16/shift_parameter_mixup.sol | 5 ++++- .../shift_parameter_mixup.sol-0.5.16.zip | Bin 1380 -> 1772 bytes .../0.6.11/shift_parameter_mixup.sol | 5 ++++- .../shift_parameter_mixup.sol-0.6.11.zip | Bin 1505 -> 1911 bytes .../0.7.6/shift_parameter_mixup.sol | 2 ++ .../0.7.6/shift_parameter_mixup.sol-0.7.6.zip | Bin 1557 -> 1865 bytes 12 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 shift_parameter_mixup.sol diff --git a/shift_parameter_mixup.sol b/shift_parameter_mixup.sol new file mode 100644 index 000000000..9681e3264 --- /dev/null +++ b/shift_parameter_mixup.sol @@ -0,0 +1,11 @@ +contract C { + + function f() internal returns (uint a, uint b) { + assembly { + a := shr(a, 8) + b := shl(248, 0xff) + } + uint y = 1; + uint g = 0xff << y; + } +} \ No newline at end of file diff --git a/slither/detectors/assembly/shift_parameter_mixup.py b/slither/detectors/assembly/shift_parameter_mixup.py index 1f6a878e2..93ac6b799 100644 --- a/slither/detectors/assembly/shift_parameter_mixup.py +++ b/slither/detectors/assembly/shift_parameter_mixup.py @@ -8,6 +8,7 @@ from slither.slithir.operations import Binary, BinaryType from slither.slithir.variables import Constant from slither.core.declarations.function_contract import FunctionContract from slither.utils.output import Output +from slither.core.cfg.node import NodeType class ShiftParameterMixup(AbstractDetector): @@ -45,8 +46,18 @@ The shift statement will right-shift the constant 8 by `a` bits""" def _check_function(self, f: FunctionContract) -> List[Output]: results = [] + in_assembly = False for node in f.nodes: + if node.type == NodeType.ASSEMBLY: + in_assembly = True + continue + if node.type == NodeType.ENDASSEMBLY: + in_assembly = False + continue + if not in_assembly: + continue + for ir in node.irs: if isinstance(ir, Binary) and ir.type in [ BinaryType.LEFT_SHIFT, diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ShiftParameterMixup_0_6_11_shift_parameter_mixup_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ShiftParameterMixup_0_6_11_shift_parameter_mixup_sol__0.txt index 354d90a13..81b72456c 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_ShiftParameterMixup_0_6_11_shift_parameter_mixup_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_ShiftParameterMixup_0_6_11_shift_parameter_mixup_sol__0.txt @@ -1,2 +1,2 @@ -C.f() (tests/e2e/detectors/test_data/incorrect-shift/0.6.11/shift_parameter_mixup.sol#3-7) contains an incorrect shift operation: a = 8 >> a (tests/e2e/detectors/test_data/incorrect-shift/0.6.11/shift_parameter_mixup.sol#5) +C.f() (tests/e2e/detectors/test_data/incorrect-shift/0.6.11/shift_parameter_mixup.sol#3-10) contains an incorrect shift operation: a = 8 >> a (tests/e2e/detectors/test_data/incorrect-shift/0.6.11/shift_parameter_mixup.sol#5) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ShiftParameterMixup_0_7_6_shift_parameter_mixup_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ShiftParameterMixup_0_7_6_shift_parameter_mixup_sol__0.txt index 1c4206ea0..09e4a60c9 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_ShiftParameterMixup_0_7_6_shift_parameter_mixup_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_ShiftParameterMixup_0_7_6_shift_parameter_mixup_sol__0.txt @@ -1,2 +1,2 @@ -C.f() (tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol#3-8) contains an incorrect shift operation: a = 8 >> a (tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol#5) +C.f() (tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol#3-10) contains an incorrect shift operation: a = 8 >> a (tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol#5) diff --git a/tests/e2e/detectors/test_data/incorrect-shift/0.4.25/shift_parameter_mixup.sol b/tests/e2e/detectors/test_data/incorrect-shift/0.4.25/shift_parameter_mixup.sol index 89a9210ad..9681e3264 100644 --- a/tests/e2e/detectors/test_data/incorrect-shift/0.4.25/shift_parameter_mixup.sol +++ b/tests/e2e/detectors/test_data/incorrect-shift/0.4.25/shift_parameter_mixup.sol @@ -1,8 +1,11 @@ contract C { - function f() internal returns (uint a) { + function f() internal returns (uint a, uint b) { assembly { a := shr(a, 8) + b := shl(248, 0xff) } + uint y = 1; + uint g = 0xff << y; } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/incorrect-shift/0.4.25/shift_parameter_mixup.sol-0.4.25.zip b/tests/e2e/detectors/test_data/incorrect-shift/0.4.25/shift_parameter_mixup.sol-0.4.25.zip index 5dd3dab128bdbaaa7d3155dc2f20b2f314edec98..17e75fa4f6606d000d6d908a01ab17370ba48483 100644 GIT binary patch delta 1617 zcmV-X2Cn(*3grzLP)h>@KL7#%4gd~`Q&=)t<7z1e002=Okr-Wn^+P_6+Z$mKkbTx89aTbXJBwQatUcmq!HffWt_>C) z6buA{!>^u6w_@LaBLV1mNa|MAEeanpNGEMcSYIly;40H<7bJ{TI^fs0c##O%PpFJf zETGefD!0$RXoSPEryu1Y$`{@+7MT3&LZrPI0frWBc?9<2mOWV~wP>_1P6BXQ&-M2b z|5=Z)hC{N-TDKN+d}YvO2wlD{MUtdE+D_A{tv}GE^N5Lm)*c;yoZqo+h+bIAJ;fL$ z-eTp3{)iAZq44BV_uaw>Kq@ad^1)NQrjo*5n6>NVvbctSVu=n_QI~df#3RE=_xCN} z>lK*yCI=8^C*UbQrTaL1C*AiGLA&(m5|;Sh_D12v|G{ibJOBJz)0+Z8)rwOdmUcN{ zmeL%Vr5sIv5tc#sK!5j7QE;*tT9zBl9+1>shy=P=#7@lrXq{?LBhV>NLdqpQWN7!#cmS#*rNAIL+IG;>UpBlrkv<~+~p+AXIUhhuXMX!KTXN> zovKSr2!_8UCXFaM^$k)r0b>CX?D_{QS|^rJY^FD*^GP;?Or<+0n|U+!Ee!V}n_gLP z%SQlztSj;PtdZf;dg~#{yym_AIOaYs4}vL`SSDGF$||zah;wjmH{u$y366rps+|UY z_gW59_8%^SJ3s?>G}SC7ZTiHGy*)KjEeW4Oimf_lxx3*RNit*5Pcvi*x9*jCCTRF&li{=#S zDB(URFg2;gt_?qJJJ205M6SlKT5ZUjt=#4Np^uuT+3V+uj76S8Rn*uJIaoR`#ou`G z(n5Ei)+$K&pXs=szgn@WvHa9Cq&Q7~S?T-BkVeKoOj?EAW>Lh@7T)BxVo%L-#- z60%c{fGh+y{go+cEn1>Ryp0Y#_?gD+IX2HvW6;rE@#Wls-l1X6oLu;V-HpA4UzL@Q zO)mlFeN_fwUVlb^-Y%V(ya`X32cvX#4{`bqGF{`zUVV+dC@M7g>+Deuqe)tS2Y#{; zbNwbu^mYgg@AF&YLDpB~iP!a`9Fu2@)vQn7*LB9{gHR{TSb>2zcHRl0sYS7PfPI)e z1ZSs}z^4GGtC0|*D0ye3iiiaX_0gp_0{dR2I-jt) z-tR&9+)hkS{C<8UlV$%6#u|x#j`4ob5n^F?2il+XwWeGV4O=+e-o}wh##k6SIS>J7 z1e8p0={%s}uUHb7ZDjvtmY;8~pN8%SP9U@7`63q zw6+ceBqI!8SDw6~ZpTQjVMxV{By7}EO)CYYiE8Q0e2FE1ZktbL-e3SpeGS1p$ppbj zD|X9Wbv=BhtLc1^@t2 P9Fr6UQ3iAd00000@Jbix delta 1243 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 d01$~&SSKx#UoZv$07V>=4FypKdj1w8-& delta 1229 zcmV;;1Ty>V4de@KL7#%4ggAxcUHR=UYV!_008w6kr-Wn@kbAZrIlV+*LwgE zaqkuAn-IgL>aAZgH7}VU1rY!WF7X_}(JsDQ-PQ4+*DFlL@@VXu8Xs8(0UD9BWkA$K>;%K)?#$Q2aq(t{$iO{x4U>nu za1S)4|B>5#QvpI?VHy~rjDeJ`1IC9Fd8#~rlFtvY2sadeBl%WGoUx_ez-d1gxz@a( zPH%3{p9xWL<^A4%Eu5dxMCZ|c0igLseNYu+0$@(l7r~-^e&tD_L^sfM!dbCgcO)q0iD%f18^xn?>P z;go9@Rzh?!XYxX?YTAH}@o*0Js;mig!ar1AetQQbBkZQ8T%?9M7%rR z=Q7J`1CQOf8a%`FArue*XC&;H4Rtl-isE^M28&I9ze1OTHQQ5+quUO^(dZ&wkOR75 zKGc`Spx92j7Y0Z7tC>fsdll>)~9SPBi~LmMwmSnh}XaI%8-O_4N)Wq2Pv1puQ^qb(XL3jGdGZBHH{|u&qGhI z7RQi(3{2Zy1Omx zj0XiBF97niwch+~@G#hqs${VVHDV$L5RB(rQ~D!h}p3rIh*Fb zz9aX(De3Qoi80UTi->h1*#UO=zw($J3JX}2V?=DFD_;tNWl@focx^I&rkN#U@g04C z$YETr1nf?Fo;L{=H7O=(i1T8kZfgh}#>^eWKkO^`^QNj7@=GH4tlE}0GRz{`8J`|! zN26ITOJcuo+MVAZx|@FbLJ7j6iT9`Vv1guZg9(Qb2_x0KOB@KL7#%4geB~Q&_Nwj^(=s005*Qkr-Wn^+P_6+Z$mK?@j3%M9e0%6{msY}nBNp8r~8Zpb) z|46!1ag&I=M0}!6w6=JXhgrAp+1ncBI9P7u)QJ-(bFlhr>-3Zb5@*K{`#FnsfuH2# zqNcisLLA0{$rJst`S4K>(}sC7Q4Wx-lmV zG42NdDE}6}pvQ)spjn#+G8hx7QVW^~y%)xE*Gtw2$ zs8uV)2`BGFt)+}@QE|d~@95M%Ta^%l*cyrGM|SM{b+@Mpb1W$K?V}&H1RN*DRv&;UCB;Y zD>|=vAZq;qg1~&3kE?1lGqnCf?-nL0T}8ttXSmkOH2fa+xEuT+O48#cxXh@hr#%MRHC5a;!2O?<7+^8V-!3D@p2l}gT=!YCsFRzv(;?tXT zOMSq9s#ayzDClJGQ zD92alArZ0LR-tsK&VkP#=&W8{(xGG{(AsZ*&QWmaQ*BDDf5pFc-t%M$E=(HQ?;j(T%(3g76;+s*NpSfp(rJVasV;iOt3R=>X{xX5mXaUp3>3`@s&|LtLYj;zF5AQRb2;mAkCUOmz z=AdZ;I_?8L(44F1#`ji77(_X*G1!|yfhGXgkO)2@W1{O$QkKNX^T@k|S7SPV6)ALE z4)O)!FxGooQ41|w1hp`LMSWQSO6doRKk`q<_P_^Uj^j}ky>mg514P`GvJLT;=?6f0 zTe$1_0}^?4BYu_Hl?zyafK#tl_!Q2wqFoe)`3*TDn7AQI{io@|%XK-3UWa_sY)TA< z&yw&~QDf{b;O_+!8h3s%bGQ(Hmtvv?0)biklRA4^>t5k2lbmO%SJmW z1w_e2j$X>YBk#a9`#sl5@GV=7UD2+4Rx>+QfaCTOUbosQpbg`z^}l*}5p;+$a&2^V zuLzx5$-Euu-|u>RhyKDPNhD-h=szq9u@L}aYHx!8ZB9?kLSF>oTdNL#r=T(jQdd>T z@mG;n#g+FiO?JlS&Z4vb?;4Xt^@60!9VA9Sz!wFiN;+ZOsh^(c2z z;ebx5&cS{y-H(5lX}(K;9q)p9clG6;f+cK)M9?#4B6q>@@=N$$F=`FI8BIR!#Eev7vd#N4yivYFTb zzb6{gW%)GV(4R)}@c;FJy+Tk+0Rle*KL7#%4geB~Q&_Nwj^(=s005*QlZpjV1_lQJ G0001ee_{y$ delta 1362 zcmV-Y1+Dt`4&e(MP)h>@KL7#%4ggAxcUBa5H1j0|000^j001qMF$XY_ODccyM-PRi zm0nlZdjJq|?-l5q5W}VAK!X$~yhYNz{x3$S;g((ndY>|}t(QLxS4R#=9E-d-ov%-s zvsBIqqzQ1b(HPZW`jlKX*T%U41fVy95lw5d@8mI552C&0l*;>c5E{Q!S$2Ly$Ugy&te+MAhBj~nDghi029@^IFqq25)a6soxSvZH%)3F`%}Pg3qETuU$WPP=@AZX=9}{~&3Ce2Yi_9KRYsv#jpZO*n z>*+$7u4S4tvQ0MF{kMPN0AJ3UOL>(T*OlP)XqY z1pI*j`hYF%>CpxgS9%IZ(LUJJmwaMzvJ6!JRw6K&*i3BOIV8EIQ_gzsvZmyCPg&Uy z?-N*HkSw#k!|e3OaRrJr!U^aMS&h)?FQm~BmoFxINB+NlT3&x^=_gP(*8jt$$gjAl zSaaTxCM{U7*Sw-6I;K0DGb$5Up0pB{-59*RU?PoAP=?(?tqFpcuvf~P-74~K3PG@v zawX4nzq~~2#c-WbghGO`OTF4l(SovO!w?Z~jWQ1Js!kKm;qW(lE<=~b9n`v-n+dLu zv3(uaEZ^!W$7_FUJ=jX@pBhZhDGkPZwSPOCmY9J7e^(05>&#l|FV4MyF9tTj=inoE z5ia8wW{B9p`Vy0yux0$)uDQ5!j#AtN|9q;v~ z#DDAh1R0tjEq)nEN>Le*x%Z1=Z7GYI@5R4_Quw1$Uy*-7koK*79OxBMkio2Eo?a_a11o1VS zc@#^UrBz^bpfrIv;a3manF_tM7$)O1)EnqIeWkaZ)UcX%X+H=r4Sf@P=81% zL+O_ZJP;M0^I<)*;(yozLW%8R#i3i;ywr=Ngi6R$J^;&;N4AhX;@86n-$NNL6c;I|nf(is+ zJJGE9^cWy67rBU;ftu!$VC~A$orqQ8(jet1UrnKi-TR`=w>KC&EP$iVQHYRbpMezh zhy)7gwJxWP3k2z<$v7%(KrsnJ$N8tx0Y-UEYJ@IV#4p|TCGbP~WzGNlE^>g~ERrc; zRh@tOUCUx0Sb@J7NV3`I3C$KmXtRVLeT$wX5ctefMMX0rLOkz=NF;d3q7X5ZDl`2n z?zS#3W~|_n9;$rT%rpv)=FToq*6hVU!!PB#cN~CAfF}Ni!gPRe!7AICIA2c diff --git a/tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol b/tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol index 11a2af9ae..9681e3264 100644 --- a/tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol +++ b/tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol @@ -5,5 +5,7 @@ contract C { a := shr(a, 8) b := shl(248, 0xff) } + uint y = 1; + uint g = 0xff << y; } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol-0.7.6.zip b/tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol-0.7.6.zip index e1cce4a17341c1df74817f1d973dffc2c27c7e16..0953de21b8d1e61cad694cae3364ce0dfa81ac05 100644 GIT binary patch delta 1725 zcmV;u215Cj49N}~P)h>@KL7#%4geF0Q&^_;Vw{Zz001u^001qM&jm1%ODcc$Lq3k% z8(|US<+$<-R-TXbNE-97FH-K9mq@1&+0=A#oo)!e&BRa?>@UL&m{xMKPC59HR5yY3 zXb#y;XNiqtuQ&uPTYTxUfArd4b56*9_256R?*c}4v(i;a;n+`X6rf^+{u&A zKApEIstRYF6!R|-o1AxbW=$x>08<8T=KDo72xpMI|7bAgSi^CooEime%%8`WMDjQ! zA~>>(&d`oKCK8ME00v9MfI;2dBhWjFpSMp242bwbKRFs{6C1SL_e+0&j<0gci{DWXoqppy#O`ueLHdJx;noG0BOrx|HD z=CrE^rG5(2q&fZab2g)cfh|)`u%TqoSgfD&fp^5)cvLi>Ta8S&l>Yq_Ki^uW8-F-X zie-Oa`8n(^jC8n)`zU{V5{i4z9SwtFI~ z9N#!`fid^cW6!fDT|gKd_zoV<7=~^zln<$4TpU9PHWAu#FR^TI@2CLEp6NOb#GACHIyCnNpNAS^@l z$tB&9dGp0*fFe0XaXZuCgL8Vhdo0@Bs?;Xwb|wQu&vr{>9omDUrhY}yWjsen{P&FS7f$i!l+03@dz0ec#C4W5>-?L|Bnn39CPlQHAhgS zr}SK;RpE*8d)>j-QKgF%>z%#k@k|Axb~g(^D|vqc(StLu^7|@G%Hk6Wp%sMo1ID_0 zM;ym({9?w@Ey7|z1^91I=DA{s>(E(29P5vY_J-^w44`z}(zjfi1(EP zYI`?y62`UO3sTc@M(C!YBhD9Ir!9(A%Ii;Mq2k`<->hIx5M{|Mn?5Ic76BFdo8&&Ujk-=m5ajFIX66YDs3bpiYh>y^woPNu(q{W(YppCi~8()di2Qor-v^MFVy2 zfkn#J5Dl}xZ1mg{8_+A8W)COfyB~j1>_yqK-*1ai$}K43KcLYzu(g;R9UbBL;FmI+ zRMF77|Nl*&LOYgqf~&fl_`6E>ZVhc6nYZ^k;c3nxLCTqz7YTt2hacuYg!-h_Wp47% zT$dKDy}Xe6wkP{{7l?wtthZH@szX>3%uW2+QQ}Zb0Rle*KL7#%4geF0Q&@KL7#%4ghDbq*hW?iU3&!006`mkr-Wn@kbAZrIlV+*LwgE zaqkuAn-IgLuMaKn4`>@Z)x=k#di^mxeF%4dss_}8dX%CJ8fW)^GwiRWt;?{{s5_AYqQnzo zai8alB*}IY_;kl;oFE$%jlh;Nhq|JVlV)ePJf8p~Ra^id__c>#XlB6jgtgQn_ZLs> z$w)xHB`&YX;xeaqr@#IG!j4F-c?Jqu-e0+2Bif`iVd+V(9J^U3-3D94Cvy*Amw4xtwT^3;_y zaFoQFv3D9U8dI-(gY94QRE;NpNXgD~TvQqRE^3bOizedj{U?j+ffjMz zZDr(G#>04AVv6S_6TqAixc+u7WzgH0yy5ljr)D~;qS_kRy;Pg}|0}bM@B=jzLUaeC z^CG4*V9IH~eV-T(V(5#(w~F56f~035Oh@)=o3YG(yUuYK=!IC%+_<#_#KID(2(M3n zC;F!=7#9^tt!_PR;56eOiNzL9jE_CpuXy4q&+|f2Wh(#;UjH#7-dHalo$-x9|EK}D z@-7pJTTb~w(#)r^0o1kN3+e57wpj2$yI<;>EFOhHPxA3SV!C1C!99geeEmW=3T&&L z2vp8;OrcA)vda+!pZ(xizHF1)K!sp`!BzVPU9>cj`0Zs5`#S%dmVDtH%>NqJ_o)`= z`L_Yj(7fgsdPup-(!vzi$l6bjMM+i3AQIdTT2b zs{9Fp5;18Jlh<_0E;*uKvarchd^INIetD Date: Mon, 19 Feb 2024 17:47:14 +0100 Subject: [PATCH 58/64] Update tests --- .../test_data/expected/assembly-all.sol-0.4.0-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.1-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.10-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.11-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.12-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.12-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.13-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.13-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.14-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.14-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.15-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.15-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.16-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.16-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.17-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.17-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.18-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.18-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.19-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.19-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.2-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.20-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.20-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.21-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.21-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.22-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.22-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.23-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.23-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.24-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.24-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.25-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.25-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.26-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.26-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.3-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.4-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.5-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.6-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.7-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.8-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.4.9-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.0-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.0-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.1-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.1-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.10-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.10-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.11-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.11-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.12-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.12-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.13-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.13-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.14-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.14-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.15-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.15-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.16-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.16-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.17-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.17-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.2-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.2-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.3-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.3-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.4-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.4-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.5-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.5-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.6-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.6-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.7-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.7-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.8-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.8-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.9-compact.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.5.9-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.0-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.1-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.10-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.11-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.12-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.2-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.3-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.4-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.5-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.6-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.7-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.8-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.6.9-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.7.0-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.7.1-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.7.2-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.7.3-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.7.4-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.7.5-legacy.json | 4 ++-- .../test_data/expected/assembly-all.sol-0.7.6-legacy.json | 4 ++-- .../expected/assembly-functions.sol-0.6.9-legacy.json | 2 +- .../expected/assembly-functions.sol-0.7.6-legacy.json | 2 +- .../test_data/expected/yul-0.4.0.sol-0.4.0-legacy.json | 2 +- .../test_data/expected/yul-0.4.1.sol-0.4.1-legacy.json | 2 +- .../test_data/expected/yul-0.4.1.sol-0.4.10-legacy.json | 2 +- .../test_data/expected/yul-0.4.1.sol-0.4.2-legacy.json | 2 +- .../test_data/expected/yul-0.4.1.sol-0.4.3-legacy.json | 2 +- .../test_data/expected/yul-0.4.1.sol-0.4.4-legacy.json | 2 +- .../test_data/expected/yul-0.4.1.sol-0.4.5-legacy.json | 2 +- .../test_data/expected/yul-0.4.1.sol-0.4.6-legacy.json | 2 +- .../test_data/expected/yul-0.4.1.sol-0.4.7-legacy.json | 2 +- .../test_data/expected/yul-0.4.1.sol-0.4.8-legacy.json | 2 +- .../test_data/expected/yul-0.4.1.sol-0.4.9-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.11-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.12-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.12-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.13-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.13-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.14-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.14-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.15-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.15-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.16-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.16-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.17-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.17-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.18-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.18-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.19-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.19-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.20-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.20-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.21-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.21-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.22-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.22-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.23-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.23-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.24-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.24-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.25-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.25-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.26-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.4.26-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.0-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.0-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.1-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.1-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.10-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.10-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.11-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.11-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.12-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.12-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.13-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.13-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.14-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.14-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.15-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.15-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.16-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.16-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.17-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.17-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.2-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.2-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.3-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.3-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.4-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.4-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.5-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.5-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.6-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.6-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.7-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.7-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.8-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.8-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.9-compact.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.5.9-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.0-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.1-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.10-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.11-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.12-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.2-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.3-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.4-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.5-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.6-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.7-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.8-legacy.json | 2 +- .../test_data/expected/yul-0.4.11.sol-0.6.9-legacy.json | 2 +- .../test_data/expected/yul-0.7.0.sol-0.7.0-legacy.json | 2 +- .../test_data/expected/yul-0.7.0.sol-0.7.1-legacy.json | 2 +- .../test_data/expected/yul-0.7.0.sol-0.7.2-legacy.json | 2 +- .../test_data/expected/yul-0.7.0.sol-0.7.3-legacy.json | 2 +- .../test_data/expected/yul-0.7.0.sol-0.7.4-legacy.json | 2 +- .../test_data/expected/yul-0.7.5.sol-0.7.5-legacy.json | 2 +- .../test_data/expected/yul-0.7.5.sol-0.7.6-legacy.json | 2 +- 198 files changed, 296 insertions(+), 296 deletions(-) diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.0-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.0-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.0-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.0-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.1-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.1-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.1-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.1-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.10-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.10-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.10-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.10-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.11-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.11-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.11-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.11-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.12-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.12-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.12-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.12-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.12-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.12-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.13-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.13-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.13-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.13-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.13-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.13-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.13-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.14-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.14-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.14-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.14-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.14-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.14-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.14-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.15-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.15-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.15-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.15-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.15-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.15-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.15-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.16-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.16-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.16-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.16-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.16-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.16-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.16-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.16-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.17-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.17-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.17-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.17-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.17-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.17-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.17-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.17-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.18-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.18-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.18-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.18-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.18-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.18-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.18-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.18-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.19-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.19-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.19-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.19-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.19-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.19-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.19-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.19-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.2-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.2-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.2-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.2-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.20-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.20-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.20-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.20-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.20-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.20-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.20-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.20-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.21-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.21-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.21-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.21-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.21-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.21-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.21-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.21-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.22-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.22-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.22-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.22-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.22-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.22-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.22-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.22-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.23-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.23-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.23-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.23-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.23-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.23-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.23-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.23-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.24-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.24-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.24-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.24-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.24-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.24-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.24-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.24-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.25-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.25-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.25-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.25-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.25-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.25-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.25-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.25-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.26-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.26-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.26-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.26-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.26-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.26-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.26-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.26-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.3-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.3-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.3-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.3-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.4-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.4-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.4-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.4-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.5-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.5-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.5-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.5-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.6-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.6-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.6-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.7-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.7-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.7-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.7-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.8-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.8-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.8-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.8-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.9-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.9-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.9-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.4.9-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.0-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.0-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.0-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.0-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.0-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.0-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.0-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.1-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.1-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.1-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.1-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.1-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.1-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.1-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.10-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.10-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.10-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.10-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.10-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.10-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.10-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.11-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.11-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.11-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.11-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.11-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.11-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.11-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.12-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.12-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.12-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.12-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.12-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.12-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.13-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.13-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.13-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.13-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.13-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.13-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.13-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.14-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.14-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.14-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.14-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.14-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.14-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.14-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.15-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.15-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.15-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.15-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.15-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.15-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.15-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.16-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.16-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.16-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.16-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.16-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.16-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.16-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.16-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.17-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.17-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.17-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.17-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.17-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.17-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.17-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.17-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.2-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.2-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.2-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.2-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.2-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.2-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.2-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.3-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.3-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.3-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.3-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.3-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.3-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.3-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.4-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.4-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.4-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.4-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.4-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.4-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.4-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.5-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.5-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.5-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.5-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.5-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.5-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.5-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.6-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.6-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.6-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.6-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.6-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.7-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.7-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.7-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.7-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.7-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.7-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.7-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.8-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.8-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.8-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.8-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.8-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.8-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.8-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.9-compact.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.9-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.9-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.9-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.9-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.9-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.5.9-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.0-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.0-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.0-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.0-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.1-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.1-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.1-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.1-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.10-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.10-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.10-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.10-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.11-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.11-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.11-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.11-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.12-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.12-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.12-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.12-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.2-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.2-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.2-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.2-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.3-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.3-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.3-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.3-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.4-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.4-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.4-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.4-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.5-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.5-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.5-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.5-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.6-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.6-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.6-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.7-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.7-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.7-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.7-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.8-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.8-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.8-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.8-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.9-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.9-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.9-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.9-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.0-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.0-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.0-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.0-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.1-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.1-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.1-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.1-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.2-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.2-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.2-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.2-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.3-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.3-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.3-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.3-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.4-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.4-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.4-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.4-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.5-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.5-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.5-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.5-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.6-legacy.json index bafe8a53d..7a501dac6 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.6-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.6-legacy.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->3;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->5;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-legacy.json index 09c0a51f7..344d6e29c 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-legacy.json @@ -1,5 +1,5 @@ { "A": { - "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n}\n" + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-legacy.json index 09c0a51f7..344d6e29c 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-legacy.json @@ -1,5 +1,5 @@ { "A": { - "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n}\n" + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.0.sol-0.4.0-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.0.sol-0.4.0-legacy.json index 8f6ef922b..cdc7d7458 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.0.sol-0.4.0-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.0.sol-0.4.0-legacy.json @@ -1,5 +1,5 @@ { "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.1-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.1-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.1-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.1-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.10-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.10-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.10-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.10-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.2-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.2-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.2-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.2-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.3-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.3-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.3-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.3-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.4-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.4-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.4-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.4-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.5-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.5-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.5-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.5-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.6-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.6-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.6-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.7-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.7-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.7-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.7-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.8-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.8-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.8-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.8-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.9-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.9-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.9-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.9-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.11-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.11-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.11-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.11-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.12-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.12-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.12-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.12-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.12-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.12-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.13-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.13-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.13-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.13-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.13-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.13-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.13-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.14-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.14-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.14-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.14-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.14-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.14-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.14-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.15-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.15-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.15-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.15-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.15-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.15-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.15-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.16-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.16-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.16-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.16-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.16-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.16-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.16-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.16-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.17-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.17-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.17-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.17-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.17-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.17-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.17-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.17-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.18-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.18-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.18-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.18-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.18-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.18-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.18-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.18-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.19-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.19-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.19-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.19-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.19-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.19-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.19-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.19-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.20-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.20-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.20-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.20-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.20-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.20-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.20-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.20-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.21-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.21-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.21-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.21-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.21-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.21-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.21-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.21-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.22-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.22-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.22-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.22-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.22-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.22-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.22-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.22-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.23-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.23-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.23-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.23-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.23-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.23-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.23-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.23-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.24-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.24-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.24-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.24-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.24-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.24-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.24-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.24-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.25-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.25-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.25-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.25-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.25-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.25-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.25-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.25-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.26-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.26-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.26-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.26-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.26-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.26-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.26-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.26-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.0-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.0-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.0-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.0-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.0-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.0-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.0-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.1-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.1-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.1-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.1-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.1-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.1-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.1-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.10-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.10-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.10-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.10-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.10-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.10-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.10-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.11-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.11-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.11-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.11-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.11-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.11-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.11-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.12-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.12-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.12-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.12-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.12-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.12-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.13-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.13-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.13-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.13-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.13-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.13-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.13-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.14-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.14-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.14-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.14-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.14-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.14-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.14-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.15-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.15-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.15-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.15-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.15-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.15-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.15-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.16-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.16-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.16-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.16-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.16-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.16-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.16-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.16-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.17-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.17-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.17-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.17-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.17-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.17-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.17-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.17-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.2-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.2-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.2-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.2-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.2-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.2-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.2-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.3-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.3-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.3-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.3-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.3-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.3-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.3-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.4-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.4-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.4-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.4-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.4-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.4-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.4-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.5-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.5-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.5-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.5-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.5-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.5-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.5-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.6-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.6-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.6-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.6-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.6-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.7-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.7-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.7-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.7-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.7-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.7-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.7-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.8-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.8-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.8-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.8-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.8-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.8-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.8-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.9-compact.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.9-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.9-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.9-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.9-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.9-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.5.9-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.0-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.0-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.0-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.0-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.1-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.1-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.1-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.1-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.10-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.10-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.10-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.10-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.11-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.11-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.11-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.11-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.12-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.12-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.12-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.12-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.2-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.2-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.2-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.2-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.3-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.3-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.3-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.3-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.4-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.4-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.4-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.4-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.5-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.5-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.5-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.5-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.6-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.6-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.6-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.7-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.7-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.7-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.7-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.8-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.8-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.8-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.8-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.9-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.9-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.9-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.9-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.0-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.0-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.0-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.0-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.1-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.1-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.1-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.1-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.2-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.2-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.2-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.2-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.3-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.3-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.3-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.3-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.4-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.4-legacy.json index a9569a2fb..afbb84ed7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.4-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.4-legacy.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.5-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.5-legacy.json index 915f1d3c4..081b6acd5 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.5-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.5-legacy.json @@ -1,5 +1,5 @@ { "C": { - "f(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n}\n" + "f(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.6-legacy.json index 915f1d3c4..081b6acd5 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.6-legacy.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.6-legacy.json @@ -1,5 +1,5 @@ { "C": { - "f(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n}\n" + "f(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: END INLINE ASM 2\n\"];\n}\n" } } \ No newline at end of file From 3ff3103cfab9d3df59872885186c8e8510a841d0 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 19 Feb 2024 21:34:15 -0600 Subject: [PATCH 59/64] fix: support renaming in base inheritance and base constructor calls --- .../slither_compilation_unit_solc.py | 62 ++++++++----------- .../test_data/inheritance_with_renaming/a.sol | 4 ++ .../test_data/inheritance_with_renaming/b.sol | 4 ++ .../test_data/inheritance_with_renaming/c.sol | 3 + tests/unit/core/test_inheritance.py | 36 +++++++++++ 5 files changed, 73 insertions(+), 36 deletions(-) create mode 100644 tests/unit/core/test_data/inheritance_with_renaming/a.sol create mode 100644 tests/unit/core/test_data/inheritance_with_renaming/b.sol create mode 100644 tests/unit/core/test_data/inheritance_with_renaming/c.sol create mode 100644 tests/unit/core/test_inheritance.py diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 21dbfff70..d67847a53 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -421,66 +421,56 @@ Please rename it, this name is reserved for Slither's internals""" self._contracts_by_id[contract.id] = contract self._compilation_unit.contracts.append(contract) + def resolve_remapping_and_renaming(contract_parser: ContractSolc, want: str) -> Contract: + contract_name = contract_parser.remapping[want] + if contract_name in contract_parser.underlying_contract.file_scope.renaming: + contract_name = contract_parser.underlying_contract.file_scope.renaming[ + contract_name + ] + target = contract_parser.underlying_contract.file_scope.get_contract_from_name( + contract_name + ) + if target == contract_parser.underlying_contract: + raise InheritanceResolutionError( + "Could not resolve contract inheritance. This is likely caused by an import renaming that collides with existing names (see https://github.com/crytic/slither/issues/1758)." + f"\n Try changing `contract {target}` ({target.source_mapping}) to a unique name." + ) + assert target, f"Contract {contract_name} not found" + return target + # Update of the inheritance for contract_parser in self._underlying_contract_to_parser.values(): - # remove the first elem in linearizedBaseContracts as it is the contract itself ancestors = [] fathers = [] father_constructors = [] - # try: - # Resolve linearized base contracts. missing_inheritance = None + # Resolve linearized base contracts. + # Remove the first elem in linearizedBaseContracts as it is the contract itself. for i in contract_parser.linearized_base_contracts[1:]: if i in contract_parser.remapping: - contract_name = contract_parser.remapping[i] - if contract_name in contract_parser.underlying_contract.file_scope.renaming: - contract_name = contract_parser.underlying_contract.file_scope.renaming[ - contract_name - ] - target = contract_parser.underlying_contract.file_scope.get_contract_from_name( - contract_name - ) - if target == contract_parser.underlying_contract: - raise InheritanceResolutionError( - "Could not resolve contract inheritance. This is likely caused by an import renaming that collides with existing names (see https://github.com/crytic/slither/issues/1758)." - f"\n Try changing `contract {target}` ({target.source_mapping}) to a unique name." - ) - assert target, f"Contract {contract_name} not found" + target = resolve_remapping_and_renaming(contract_parser, i) ancestors.append(target) elif i in self._contracts_by_id: ancestors.append(self._contracts_by_id[i]) else: missing_inheritance = i - # Resolve immediate base contracts + # Resolve immediate base contracts. for i in contract_parser.baseContracts: if i in contract_parser.remapping: - contract_name = contract_parser.remapping[i] - if contract_name in contract_parser.underlying_contract.file_scope.renaming: - contract_name = contract_parser.underlying_contract.file_scope.renaming[ - contract_name - ] - fathers.append( - contract_parser.underlying_contract.file_scope.get_contract_from_name( - contract_name - ) - # self._compilation_unit.get_contract_from_name(contract_parser.remapping[i]) - ) + target = resolve_remapping_and_renaming(contract_parser, i) + fathers.append(target) elif i in self._contracts_by_id: fathers.append(self._contracts_by_id[i]) else: missing_inheritance = i - # Resolve immediate base constructor calls + # Resolve immediate base constructor calls. for i in contract_parser.baseConstructorContractsCalled: if i in contract_parser.remapping: - father_constructors.append( - contract_parser.underlying_contract.file_scope.get_contract_from_name( - contract_parser.remapping[i] - ) - # self._compilation_unit.get_contract_from_name(contract_parser.remapping[i]) - ) + target = resolve_remapping_and_renaming(contract_parser, i) + father_constructors.append(target) elif i in self._contracts_by_id: father_constructors.append(self._contracts_by_id[i]) else: diff --git a/tests/unit/core/test_data/inheritance_with_renaming/a.sol b/tests/unit/core/test_data/inheritance_with_renaming/a.sol new file mode 100644 index 000000000..6f1429e91 --- /dev/null +++ b/tests/unit/core/test_data/inheritance_with_renaming/a.sol @@ -0,0 +1,4 @@ +import {B as Base} from "./b.sol"; +contract A is Base(address(0)) { + constructor (address x) {} +} \ No newline at end of file diff --git a/tests/unit/core/test_data/inheritance_with_renaming/b.sol b/tests/unit/core/test_data/inheritance_with_renaming/b.sol new file mode 100644 index 000000000..dd85ad3dd --- /dev/null +++ b/tests/unit/core/test_data/inheritance_with_renaming/b.sol @@ -0,0 +1,4 @@ +import {C as C2} from "./c.sol"; +contract B is C2 { + constructor (address x) C2(x) {} +} \ No newline at end of file diff --git a/tests/unit/core/test_data/inheritance_with_renaming/c.sol b/tests/unit/core/test_data/inheritance_with_renaming/c.sol new file mode 100644 index 000000000..722acdd21 --- /dev/null +++ b/tests/unit/core/test_data/inheritance_with_renaming/c.sol @@ -0,0 +1,3 @@ +contract C { + constructor (address) {} +} \ No newline at end of file diff --git a/tests/unit/core/test_inheritance.py b/tests/unit/core/test_inheritance.py new file mode 100644 index 000000000..a34f15ed4 --- /dev/null +++ b/tests/unit/core/test_inheritance.py @@ -0,0 +1,36 @@ +from pathlib import Path + +from slither import Slither +from crytic_compile import CryticCompile +from crytic_compile.platform.solc_standard_json import SolcStandardJson + +TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" / "inheritance_with_renaming" + +# https://github.com/crytic/slither/issues/2304 +def test_inheritance_with_renaming(solc_binary_path) -> None: + solc_path = solc_binary_path("0.8.15") + standard_json = SolcStandardJson() + for source_file in Path(TEST_DATA_DIR).rglob("*.sol"): + print(source_file) + standard_json.add_source_file(Path(source_file).as_posix()) + compilation = CryticCompile(standard_json, solc=solc_path) + slither = Slither(compilation) + + a = slither.get_contract_from_name("A")[0] + b = slither.get_contract_from_name("B")[0] + c = slither.get_contract_from_name("C")[0] + + assert len(a.immediate_inheritance) == 1 + assert a.immediate_inheritance[0] == b + assert len(a.inheritance) == 2 + assert a.inheritance[0] == b + assert a.inheritance[1] == c + assert len(a.explicit_base_constructor_calls) == 1 + a_base_constructor_call = a.explicit_base_constructor_calls[0] + assert a_base_constructor_call == b.constructor + + assert len(b.inheritance) == 1 + assert b.inheritance[0] == c + assert len(b.immediate_inheritance) == 1 + assert b.immediate_inheritance[0] == c + assert len(b.explicit_base_constructor_calls) == 0 From e580b2ff2890c24f13ce121df37f6ffa9d7ee80b Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 19 Feb 2024 21:39:08 -0600 Subject: [PATCH 60/64] pylint --- tests/unit/core/test_inheritance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/core/test_inheritance.py b/tests/unit/core/test_inheritance.py index a34f15ed4..d3702e2a5 100644 --- a/tests/unit/core/test_inheritance.py +++ b/tests/unit/core/test_inheritance.py @@ -1,8 +1,8 @@ from pathlib import Path -from slither import Slither from crytic_compile import CryticCompile from crytic_compile.platform.solc_standard_json import SolcStandardJson +from slither import Slither TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" / "inheritance_with_renaming" From 052a30a191162fb18884e5a3fb426270162eb3db Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 19 Feb 2024 22:06:35 -0600 Subject: [PATCH 61/64] add regression test for https://github.com/crytic/slither/issues/2313 --- examples/scripts/data_dependency.py | 14 ++++++++++++++ examples/scripts/data_dependency.sol | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/examples/scripts/data_dependency.py b/examples/scripts/data_dependency.py index 23c82cae1..5edbe4923 100644 --- a/examples/scripts/data_dependency.py +++ b/examples/scripts/data_dependency.py @@ -126,3 +126,17 @@ print(f"{var_tainted} is tainted: {is_tainted(var_tainted, contract)}") assert is_tainted(var_tainted, contract) print(f"{var_not_tainted} is tainted: {is_tainted(var_not_tainted, contract)}") assert not is_tainted(var_not_tainted, contract) + +print("SimpleModifier contract") +contracts = slither.get_contract_from_name("SimpleModifier") +assert len(contracts) == 1 +contract = contracts[0] +dependent_state_var = contract.get_state_variable_from_name("owner") +assert dependent_state_var +baz = contract.get_modifier_from_signature("baz()") +intermediate = baz.get_local_variable_from_name("intermediate") +assert intermediate +print( + f"{intermediate} depends on msg.sender: {is_dependent(intermediate, SolidityVariableComposed('msg.sender'), baz)}" +) +assert is_dependent(intermediate, SolidityVariableComposed("msg.sender"), baz) diff --git a/examples/scripts/data_dependency.sol b/examples/scripts/data_dependency.sol index a4f64870a..b4baf5c09 100644 --- a/examples/scripts/data_dependency.sol +++ b/examples/scripts/data_dependency.sol @@ -115,3 +115,12 @@ contract PropagateThroughReturnValue { return (var_state); } } + +contract SimpleModifier { + address owner; + modifier baz { + bool intermediate = msg.sender == owner; + require(intermediate); + _; + } +} \ No newline at end of file From 47fdb81e3c264cf10aea17e3f20b478396c32735 Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 20 Feb 2024 12:31:07 +0100 Subject: [PATCH 62/64] Delete file --- shift_parameter_mixup.sol | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 shift_parameter_mixup.sol diff --git a/shift_parameter_mixup.sol b/shift_parameter_mixup.sol deleted file mode 100644 index 9681e3264..000000000 --- a/shift_parameter_mixup.sol +++ /dev/null @@ -1,11 +0,0 @@ -contract C { - - function f() internal returns (uint a, uint b) { - assembly { - a := shr(a, 8) - b := shl(248, 0xff) - } - uint y = 1; - uint g = 0xff << y; - } -} \ No newline at end of file From a99f90b9765c9eb66a23f0eece72174e2301d648 Mon Sep 17 00:00:00 2001 From: Judy Wu Date: Tue, 20 Feb 2024 09:01:13 -0500 Subject: [PATCH 63/64] remove unnecessary use of list comprehension --- slither/tools/upgradeability/checks/variables_order.py | 8 ++++---- slither/utils/upgradeability.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/slither/tools/upgradeability/checks/variables_order.py b/slither/tools/upgradeability/checks/variables_order.py index fce0a09bb..8d525a6dd 100644 --- a/slither/tools/upgradeability/checks/variables_order.py +++ b/slither/tools/upgradeability/checks/variables_order.py @@ -115,8 +115,8 @@ Avoid variables in the proxy. If a variable is in the proxy, ensure it has the s def _check(self) -> List[Output]: contract1 = self._contract1() contract2 = self._contract2() - order1 = [variable for variable in contract1.stored_state_variables_ordered] - order2 = [variable for variable in contract2.stored_state_variables_ordered] + order1 = contract1.stored_state_variables_ordered + order2 = contract2.stored_state_variables_ordered results: List[Output] = [] for idx, _ in enumerate(order1): @@ -236,8 +236,8 @@ Avoid variables in the proxy. If a variable is in the proxy, ensure it has the s def _check(self) -> List[Output]: contract1 = self._contract1() contract2 = self._contract2() - order1 = [variable for variable in contract1.stored_state_variables_ordered] - order2 = [variable for variable in contract2.stored_state_variables_ordered] + order1 = contract1.stored_state_variables_ordered + order2 = contract2.stored_state_variables_ordered results = [] diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index e8300ba84..dd7bfe465 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -81,8 +81,8 @@ def compare( tainted-contracts: list[TaintedExternalContract] """ - order_vars1 = [v for v in v1.stored_state_variables_ordered] - order_vars2 = [v for v in v2.stored_state_variables_ordered] + order_vars1 = v1.stored_state_variables_ordered + order_vars2 = v2.stored_state_variables_ordered func_sigs1 = [function.solidity_signature for function in v1.functions] func_sigs2 = [function.solidity_signature for function in v2.functions] @@ -300,8 +300,8 @@ def get_missing_vars(v1: Contract, v2: Contract) -> List[StateVariable]: List of StateVariables from v1 missing in v2 """ results = [] - order_vars1 = [v for v in v1.stored_state_variables_ordered] - order_vars2 = [v for v in v2.stored_state_variables_ordered] + order_vars1 = v1.stored_state_variables_ordered + order_vars2 = v2.stored_state_variables_ordered if len(order_vars2) < len(order_vars1): for variable in order_vars1: if variable.name not in [v.name for v in order_vars2]: From 123760a62d73ae6d169db218aa4c750934f2bd3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:39:37 +0000 Subject: [PATCH 64/64] Bump docker/metadata-action from 4 to 5 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4 to 5. - [Release notes](https://github.com/docker/metadata-action/releases) - [Upgrade guide](https://github.com/docker/metadata-action/blob/master/UPGRADE.md) - [Commits](https://github.com/docker/metadata-action/compare/v4...v5) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index e0e303ed8..29f0ac2e0 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,7 +30,7 @@ jobs: - name: Set Docker metadata id: metadata - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: | ghcr.io/${{ github.repository }}