From cd3f2d41850c5744335e9592bd491a65d1bea5de Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 18 Oct 2023 14:07:10 -0500 Subject: [PATCH 01/78] Update Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d0a7d67bef..6de5ec2c66 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,6 +47,6 @@ ENV PATH="/home/slither/.local/bin:${PATH}" RUN --mount=type=bind,target=/mnt,source=/wheels,from=python-wheels \ pip3 install --user --no-cache-dir --upgrade --no-index --find-links /mnt --no-deps /mnt/*.whl -RUN solc-select install 0.4.25 && solc-select use 0.4.25 +RUN solc-select use latest --always-install CMD /bin/bash 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 02/78] 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 e69de29bb2..0000000000 diff --git a/slither/core/children/child_event.py b/slither/core/children/child_event.py deleted file mode 100644 index e69de29bb2..0000000000 From 8d9199ed6cd6498b6c0fe9229c02a78ccd9e64fc Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 18 Oct 2023 14:14:05 -0500 Subject: [PATCH 03/78] Update installation instrucitons --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0f548d6b88..6ab019b779 100644 --- a/README.md +++ b/README.md @@ -73,14 +73,14 @@ If you're **not** going to use one of the [supported compilation frameworks](htt ### Using Pip ```console -pip3 install slither-analyzer +python3 -m pip install slither-analyzer ``` ### Using Git ```bash git clone https://github.com/crytic/slither.git && cd slither -python3 setup.py install +python3 -m pip install . ``` We recommend using a Python virtual environment, as detailed in the [Developer Installation Instructions](https://github.com/trailofbits/slither/wiki/Developer-installation), if you prefer to install Slither via git. From 112786f890123497b6968480246575c8f41043ad Mon Sep 17 00:00:00 2001 From: Amos Dominion <121090896+VIELITE@users.noreply.github.com> Date: Mon, 23 Oct 2023 08:54:10 -0400 Subject: [PATCH 04/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f548d6b88..c4b4457835 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ * Correctly parses 99.9% of all public Solidity code * Average execution time of less than 1 second per contract * Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action) -* Support for Vyper +* Support for Vyper smart contracts ## Usage From 0cd9efec6fdf65e1867805f8ae7d8df26a03496b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 23:03:33 +0000 Subject: [PATCH 05/78] Bump actions/setup-node from 3 to 4 Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cb8f0ea6e1..1660a25e9c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: pip install ".[test]" - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '16' cache: 'npm' From c1a1675259abf5ebf191176b2176fa6a50b96e2f Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Tue, 24 Oct 2023 18:42:29 +0400 Subject: [PATCH 06/78] 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 c4c5c71772..77b3269454 100644 --- a/slither/solc_parsing/declarations/modifier.py +++ b/slither/solc_parsing/declarations/modifier.py @@ -92,7 +92,9 @@ def analyze_content(self) -> None: 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 07/78] 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 77b3269454..dfacc87038 100644 --- a/slither/solc_parsing/declarations/modifier.py +++ b/slither/solc_parsing/declarations/modifier.py @@ -92,7 +92,7 @@ def analyze_content(self) -> None: 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 08/78] 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 e803154d00..d2baaf7e7b 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -1500,10 +1500,13 @@ def is_reentrant(self) -> bool: """ 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 @@ def is_reentrant(self) -> bool: ] 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 cea207613a..f75198d24b 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 09/78] 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 87853aa34a..6221fd8bdc 100644 --- a/slither/core/compilation_unit.py +++ b/slither/core/compilation_unit.py @@ -16,6 +16,7 @@ ) 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 @@ def __init__(self, core: "SlitherCore", crytic_compilation_unit: CompilationUnit 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 @@ def structures_top_level(self) -> List[StructureTopLevel]: 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 f6e902e06f..9d727da8e7 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 458f951f56..5403d227ad 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -33,7 +33,7 @@ from slither.utils.type_helpers import LibraryCallType, HighLevelCallType, InternalCallType from slither.core.declarations import ( Enum, - Event, + EventContract, Modifier, EnumContract, StructureContract, @@ -73,7 +73,7 @@ def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope 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 @@ def enums_as_dict(self) -> Dict[str, "EnumContract"]: ################################################################################### @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 1b58ff63b0..7149e20c01 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 @@ def full_name(self) -> str: 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 0000000000..652f8ca20c --- /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 0000000000..5f9f1774d1 --- /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 937a051361..784b17cb20 100644 --- a/slither/core/scope/scope.py +++ b/slither/core/scope/scope.py @@ -7,6 +7,7 @@ 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 @@ def __init__(self, filename: Filename) -> None: # 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 @@ def __init__(self, filename: Filename) -> None: # 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 @@ def add_accesible_scopes(self) -> bool: 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 3535f2604d..b1bb7c66b8 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -269,6 +269,8 @@ def _compute_offsets_to_ref_impl_decl(self): # pylint: disable=too-many-branche 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 3dd6e2fd5d..34e2f24308 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -4,7 +4,7 @@ from slither.core.declarations import ( Modifier, - Event, + EventContract, EnumContract, StructureContract, Function, @@ -747,12 +747,12 @@ def analyze_events(self) -> None: 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 6531e65365..4a7d62389d 100644 --- a/slither/solc_parsing/declarations/event.py +++ b/slither/solc_parsing/declarations/event.py @@ -8,7 +8,7 @@ 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 @@ def __init__(self, event: Event, event_data: Dict, contract_parser: "ContractSol @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 2261350b4f..e7fa995215 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 85921ce742..08ee62d804 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.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.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 @@ def parse_top_level_items(self, data_loaded: Dict, filename: str) -> None: 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 55e1af21d3..9cb2abc3f1 100644 --- a/slither/tools/flattening/flattening.py +++ b/slither/tools/flattening/flattening.py @@ -77,6 +77,7 @@ def __init__( 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 6ca9c6557f..2acd43e0fa 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -24,7 +24,7 @@ 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 @@ def parse_state_variables(self) -> None: 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 bc57dc51b5..61250c5af0 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -462,6 +462,7 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]: 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 0000000000..fa64e1bf7c --- /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 0000000000..58c6a3ab60 --- /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 912d6b2e4e21a770437abbb5ac9e260f50ffa873 Mon Sep 17 00:00:00 2001 From: Usmann Khan Date: Thu, 16 Nov 2023 14:16:26 -0800 Subject: [PATCH 10/78] Error when a missing contract is specified to read-storage. Previously this just silently exited --- slither/tools/read_storage/__main__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/slither/tools/read_storage/__main__.py b/slither/tools/read_storage/__main__.py index 8415ae185f..3baa5d351a 100644 --- a/slither/tools/read_storage/__main__.py +++ b/slither/tools/read_storage/__main__.py @@ -7,6 +7,7 @@ from crytic_compile import cryticparser from slither import Slither +from slither.exceptions import SlitherError from slither.tools.read_storage.read_storage import SlitherReadStorage, RpcInfo @@ -129,6 +130,8 @@ def main() -> None: if args.contract_name: contracts = slither.get_contract_from_name(args.contract_name) + if len(contracts) == 0: + raise SlitherError(f"Contract {args.contract_name} not found.") else: contracts = slither.contracts From a793c3f1b9f364e0062b6203e04c1a93bac8e164 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 20 Nov 2023 11:43:31 +0100 Subject: [PATCH 11/78] 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 83c5658ca4..290447aa8e 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.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 a32b79d8dc..e0f35861af 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 a32b79d8dc..e0f35861af 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 a32b79d8dc..e0f35861af 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 a32b79d8dc..e0f35861af 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 zcmV-w8kOazB*rxvP)h>@KL7#%4gkkobXVhF3!NAm006Qj0g)M1fAvE?j@uhy5#!~! z@(Wg;kM&3z^RO>c?wFTIrx4lHba9<-2)@n4P!#Mh!wr~LafddB0$(QLY7Y= zA-L=%^NWd6q^Aqe-y8utMVor)<6k5uD*MD9w)Ju)#um(qm!7W&81Z!X|c1f zab>r{pAvlCe;Jg(vEsN06KU4Nh7S$3GN&0bh)Z_hoa;gKu?39@D`)++tN+#I)Y ztLz7r=f?_zYYgwjI7w0afx5RI!dM0TK~%=vx=(fTe@2n#jt^U7*F|zH2l!jye+Yrl zI#|Y5N+$&VbQSU)FUFbIK7^denh~UtT;=(GLc`IM#N#329=Ou~X`;nuzktXqY}L&^ z(A!MBpvRi<^_)^D6u5n)MO!QOsFEknh_YEn6JXh!%KIKppI1L<^<9Q9=pc9jsxHm$ z#A6_+fBht#{9ZqX4a_2r{%I(E)ngcuR)M1zI@g}Hed=|cQU&sm)lR)DWZ?q5xOv<$ z$X=$nT%$bxfTvSl`a$d>Tb^{-XqKCK*hWOVXcfs*Q{f zp>mTlLz@HuJKq2sh?dI_^S;IpW3kCN2NelqBST!qa^tQiL;wf8*a9vK+GpN?KL{}% zGfNP^GMdgzG(!V5?kBEJ7VJcC%8F)oaB;$B`ezxz3d-B{ydX4-k^k%1d@ZG#e@R#= zk6JgUytlh%|6g!6z%#T%Am*+*8~3BQlNRsX@eo$tZ+#gK(Edc16pA!r0V%Yv)Z$|q z)M#QeZnD>R66fgXU*$@b%C>*4IgaRca&H?f#yjd9BQO275K{B8o*70$*Z(8J(%7+{ z{tP?9GOhO2uy#$wzwL62=lazme^L`0Q(jyN6yo>oCYlyUC>=EO>dNG#K}aY>LidD` zWno}j$K?m9;yOlDu1D1~NU(=xq>V!skce@HP{oUHs+H`PHh88pXlU`eouvOjPLidu5UR_Pn|ELp_01nfD8r8<{3CSaJeJJ@COf09SJb)dOg zNyyR&k@-y*O(B`|MsU_^%5%yF&>f|$!7WDh!ZT*OfGpKLO{)30JT&f%%zTm!=g4y3ZC2>aEPJC zWrjTt!*jvB=gWHecVv9cf4yTX_u|(10#mCE90rSTY2y6^JkJqcO)|~LD}M@R$=uED z+V)>?g$?|yn_3;_AyC44SF2nF2FA#It3gU)1)-FK^`5`#N{7dv8rQ}Wp#7`MF*%Gz zt<74mce)f#Wz!{pA8a>r<6@y}X%AAj`WIiTwz=k=BhQB8klA4cf9r&W0FODOwo+Y}6MD*ecnJc857Mx6I7IUvH1<7*T%H|0N?36|_i$1U^zXr2bxK z?j27V|Cfz?ftV;ryJdm-A*Cx>GdP_i$ch6{N}*ff7qOO)BG>-4weCF< zW?loS02FddAt@%mH|obctdiX}e{=gsR12wjeBfEj_w^p~eCNo}5-A|IMy2p1K1kiW z-h(2FfAMUg2oEchZR@YWQJp>;mLM}mj?N?bQDg0EvsdJg5qPj9gZv4*vTRt+xfUZx z90!&bUTLMv8RbI1N}Y>4YPmwAJ}+gKX4btnBzLTUf2OVeYTbzZ`$1kJWcy?fQbYO|<9$@H zF`hI4!K-e-i9`YaB|9hd%8*C>pu&%?7QZ9mpS~M)b69+JX9^)XS@n}|-dtxrUgFvY zl-_S^Z~eKCTZNgeZ1Zs^MW#cj9ti7;IbI?{e96aJkYQ51Dl1SVKsN??kctve&9!#V zf9Nmjx;%%zUwtg@ z+fi995>am}j@lM1pkYSqqCqL`;ss5Sbzcag?RUF0K7dU#i>Wh*{Aix%bs*sgb^6RV zQlp0@P9AB-HhN(5DzY=*d98Zb3DPX?GrP_zkBvS?j)XNGFlYB79xCO^l$cAIPsv+V4c9HumjUfZe`}?p-`Ns$x`fZ;i4l9 zmH5_1B7IQQn|s@rbT4200&oXiU-=TbJ*(EhA zD%ojN9)s~aiXI-?VN!7s4xA6~f82%}BjGM&RJ8!2(+G2|%@drX@dl=(xMUc0VF0-TD&@_$Ift2Be@=HUq(g40&O4iMUr`mN%6L)K148v-4x6OKh*gXfL#WpF{V$+#A13{tMzK<|0j{XBZ zid}aDN~%M4H0vUwtgpC4Y5-^BaA%RA8Ca%@YH`0DmUSndB5+6)Tg2#(_|B?)Wc~%O zGA(lx07oiR5&cnPe{g;#FdfsaWn>5>U;2V2IqF=Bn93$fXtqO6lnA54W zpHM9@MF98RE6A?bc+2u*@VBEe%6eToK*#lIK(L>%)Q!5exb$y3 zfqZfasO;I~RF4GU*jAGFQq4yJkG8syh^-wLbX^2r8VpBiX_x4Ro32jXSpw5-;yV*K z(CgqhIT~u4OoswLGWWvLd!RS7^q@R8ushSSrLe-66-&if=&q?M*XhE&+C?s3q2Jhk zaf<(c@MM4%f1N;RDk;ZfG--?!fOD}Sc?dq?)rW?x?`6a>SrW;73a*97OXg-462O=PI+qG@Kp1o}6Utoy%zF{JSs+1GR1jsthQH_yrV;qcoT`6Hv9{^5s z%)eCcl|GQDxR?aDg%c|GBFS?S;rmjke>9u1t;w9HZLM%&Wimv=Ytb~U43+~b06te> zmymITBXs^iRce7s8JL0061_H3j4k2G5lzQRO4q-4USsx`1!ktA9M2iU<~Psif~^iL zd*&~Qm7dcicpYXCnSxylpOtLu)l`EdaiY~k$;jMLYPsjSd>P9k)qzs~NmmzRibSo(!uiwwx( z^;$kUVN+Af6`FF|;~sZTrC{HTmcK}_PxZMqd5g%9KE@FFn`SU&DeBUwMSpd*vF+am z8Sbr0-&~-(PHdYK)sxjushd?5%oj(MRjPQA=Q(*^|0XfESLW-#GjGb?e;szF)o!~F zND=wP?jQN1sqd$_xRhrVs=>?oHMqgPDCH>wL(h3(j#1Ui5mN{ptLKK0+ve^?u{C|3 z8DTPB_jR!aLm=?$PC_7ZTt)0vRM)xse&RJ;zEpE8nb$9@xO#hSr@XDK;&UvMpS_8thB86m9nt4(k*pW3==ok~9{K&AR zQcbtc$U~~t484p2eK#6LIa?~VyVQZbEN>F}J=Hu7nP)xWh&EwiMguiy+LtmW25Bej z#<338qigVpA6Xj=Iue{^Y<)7}9zCC={W~%Ck(7WRxMFPR&#zrde;F;(M`c&s{ZIT> zj2lcyP$O8(;e|McZVdHEwTkeH+m z@I`YAS9MSm{a8wnLCsoqQQR8P)5gZiD`t0Mm#}~mRC}+Ce_QcFrIL9PGI%Xze4`7c zN%I5-GxZ`Av`(kB>*1sfycbfFcW?3UpSi$x~sJV=yyM2ZZytGGk0EfZ^^f?CHR6y;*A~s-`0Bv#Z)nMp~w`!t0Wd`fT?A4 zzeprru1<3ne-6PWK-ft!sX7?x#c`VEN{Cml%;N2#^ctf7SsPYj;P;*wbs^=N( zUzDri{)AJ`-hQ$!%E$Dg=2*JILVXch)zib7@cITX>#1+T7|yA>kO7peQSTSTgBBz$ zt>$DbkDzlaHYJrDh^2M+8O-_Gb1NU#-A3tv;kE}kO(gm=Y+D=Pn+T96FW@Y-T<2gI z;R~3-f0Kl|?h<~2#=6y_3v4rU-%s{El0AyO;BP(K=8?^D?VzmcStuU(N z)FxdqG{(2QFuQ)E784KGXY6-@cJC?XfIgKbtK&UBPs>UCWD)D8o-a3DI zV{n@b6q{W&ue@Ic5ILO`^=@vs!k{?$9= ze|{}@iaDrMHB->G%v+2P=o{h=g0~_Y_gXDIc6q6a%NM|7=g{`R!4);}?DKYh<3U7Q zke$l3T>S0|#%APl)?F1AH;!}A-m%(DjshSOkx6fV37xVcp6?~!?=ALLs% z=$N2!{p7i559FKEGJz3ibb!8GUKCH?$Jk?(gnK@2{NUl^4Dz3n&ZYeT$**^}f6@Gp zc8k)?;ywKCDU?7G{B8~C;0l5#9Ktd|G8wTxwK-}CbSQu7(@g!9a%*HW?6PkKk;fJi zPqGO6vv0nt>Z6ab<-v-yNQH z0=67m*@vpjn%P%X{k&?@BXbEif4OQ1`%R94jkl>UPYW`iNj{5~B~PH#P@+xhe$+=o zkh>fb9_DZ>ZuLm5C8JFvRzypMa6WVA6;-5UW=#`GH*)Mpx=Vg90F^)(W1wsw`w5^Z zyhVIfvylwwDaU|4io09Jr*XmwEPp!=Os=!YWMnP9mxB`e2@fw9VZSyyfAE7u?VDgS za|V84H;QH@8wocNZiy8GLq^k|pFfQll@D$*X?cBRQPLM*;`NLe7|Sr4+s*e@?F3%9 zn<5|ycOqo{547gvq_9HE44%|?6TE+rVer4Ch@Ptqj6aq$?rn)MN*%&L))53aL%`9Z z4)5TkVZM|ZNTz>xd`WsIe@;kLFYI`pBB59>LRNri9b&oX909>Idn5gRTda`<>Li`P z5sCu_!_>NXPDoE=tTF+qm~rDsQ1@ZVmwd7JJJeZ#w7hoGnb_kWvDAgB=nwzUX|BIeO928u13v%)01g1hTy$6CUkjZW8UO&YB>|Jz M5lIGI8UO$Q0K%~x$p8QV delta 4538 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 Date: Mon, 4 Dec 2023 22:43:16 +0000 Subject: [PATCH 12/78] 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 f04436bd38..4a646bb42d 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 13/78] 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 29356c0c6b..d92e5b091f 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 14/78] 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 29356c0c6b..eca7ef0b28 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 15/78] 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 7b4d61e89f..e0ab4b5434 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 16/78] 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 b4d75e51af..9816dd6e24 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 17/78] 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 84286ce66c..fde87e5e2c 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -2,7 +2,8 @@ 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.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 @@ ################################################################################### ################################################################################### - 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 @@ def __call__( 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 405888f8bf..370f419c18 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 a16a8252e2..9dccc9f131 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 d4a7c54868..9e7b143ae8 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 169d8725e4..ab295e2958 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -4,9 +4,10 @@ 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 @@ def __init__( ) @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 @@ def mutate(self) -> None: 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 feb479c5c8..80d610a69a 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 0000000000..800232a5a5 --- /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 d773ea7844..03ccadec77 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 0000000000..82d6c11c98 --- /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 0000000000..1c7de9acf8 --- /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 18/78] 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 fde87e5e2c..9cb1a9f8da 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 370f419c18..b1c55d184f 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 9dccc9f131..1c99b24eef 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 9e7b143ae8..bb1c4cabe0 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 ab295e2958..a79f459061 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 @@ def _mutate(self, test_cmd: str, test_dir: str) -> Dict: """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 @@ def mutate(self, testing_command: str, testing_directory: str) -> int: # 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 5508fb68e5..5a9465c860 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 800232a5a5..c041f76d6e 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 82d6c11c98..4e3f91454b 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 1c7de9acf8..61b9db2141 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 19/78] 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 9cb1a9f8da..201b39acdd 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -4,6 +4,7 @@ import sys from typing import Type, List, Any, Dict, Tuple import os +import shutil from crytic_compile import cryticparser @@ -12,12 +13,12 @@ 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 @@ def __call__( ################################################################################### ################################################################################### - 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 0000000000..382a08aeec --- /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 b1c55d184f..d76369d4d4 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 1c99b24eef..15b2a20c3a 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 bb1c4cabe0..5e7c0a6e1b 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -4,41 +4,32 @@ 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 0000000000..9a8942e196 --- /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 0000000000..ac35d9540e --- /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 0000000000..6d5862e765 --- /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 a79f459061..e58b705a19 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 @@ 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)]: + 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 @@ def mutate(self, testing_command: str, testing_directory: str, contract_name: st 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 5a9465c860..4b0c3b1ada 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 c041f76d6e..70f7deb116 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -4,9 +4,10 @@ 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 03ccadec77..6c0ba65117 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.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 61b9db2141..7ab4065191 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -2,8 +2,13 @@ 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 20/78] 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 201b39acdd..aba4273555 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 @@ def __call__( 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 0000000000..f248d3c771 --- /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 0000000000..8c70756a24 --- /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 0000000000..7878a20eaa --- /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 382a08aeec..b00b130001 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 @@ def _mutate(self) -> Dict: # 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 d76369d4d4..1cc0fdb6db 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -2,6 +2,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 +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 15b2a20c3a..13a4e6d1a6 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 5e7c0a6e1b..e705ff94af 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 0000000000..1e20674251 --- /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 9a8942e196..6a2ef6426f 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 @@ def _mutate(self) -> Dict: # 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 ac35d9540e..6797c0c35f 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -3,6 +3,7 @@ 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 @@ "(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 6d5862e765..60e8c22c35 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 e58b705a19..ead78ac979 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 @@ def __init__( 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 @@ def mutate(self, testing_command: str, testing_directory: str, contract_name: st # 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 4b0c3b1ada..3f4e590436 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 6c0ba65117..0000000000 --- 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 4e3f91454b..0000000000 --- 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 7ab4065191..61a688f7c5 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 21/78] 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} (81%) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index aba4273555..c41a82e35f 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -2,12 +2,10 @@ 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 @@ def __call__( 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 f248d3c771..39e3a6a20e 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 @@ 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 @@ def _mutate(self) -> Dict: 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 8c70756a24..04ad8f8b03 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 @@ 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 @@ def _mutate(self) -> Dict: 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 7878a20eaa..de9ad287e1 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 0000000000..5709346b15 --- /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 0000000000..99228913aa --- /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 b00b130001..fa66c7bca2 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 @@ 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 @@ def _mutate(self) -> Dict: 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 1cc0fdb6db..f5bc52b16e 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 13a4e6d1a6..3c334e9e68 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 e705ff94af..7f75b1dcf1 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -2,13 +2,12 @@ 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 1e20674251..c6bacf485d 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 @@ def _mutate(self) -> Dict: 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 0000000000..96aebc68f9 --- /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 6a2ef6426f..e1c78c1eb0 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 @@ 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 @@ def _mutate(self) -> Dict: 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 6797c0c35f..91c05b884e 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 @@ "(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 81% rename from slither/tools/mutator/mutators/UOI.py rename to slither/tools/mutator/mutators/UOR.py index 60e8c22c35..671ee676d5 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 @@ 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 ead78ac979..5223e2d81f 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 @@ def __init__( 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 @@ def __init__( 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 @@ def __init__( # 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 @@ def mutate(self) -> Tuple[int, int]: 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 3f4e590436..9aa81a0fc4 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 80d610a69a..042b4fff70 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 70f7deb116..d61bba58af 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 61a688f7c5..6c6e80a556 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -7,38 +7,44 @@ 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 22/78] 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 c41a82e35f..8cbb103adc 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 5223e2d81f..bd40ad6acd 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -97,7 +97,7 @@ def get_exist_flag(self) -> bool: 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 6c6e80a556..65cf78c276 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 23/78] 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} (67%) create mode 100644 slither/tools/mutator/utils/patch.py diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 8cbb103adc..66c0941a6d 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 @@ def __call__( 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 39e3a6a20e..61eed67b1f 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 @@ def _mutate(self) -> Dict: 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 04ad8f8b03..e6fa414378 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 @@ def _mutate(self) -> Dict: 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 de9ad287e1..5ca46950fe 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 @@ def _mutate(self) -> Dict: 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 0000000000..1935c43e60 --- /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 5709346b15..3758306f3f 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 @@ def _mutate(self) -> Dict: 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 99228913aa..c9966f1bec 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -2,7 +2,7 @@ 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 fa66c7bca2..e6903a01e9 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 @@ def _mutate(self) -> Dict: # 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 f5bc52b16e..0217324e09 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 @@ def _mutate(self) -> Dict: # 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 3c334e9e68..c81182c432 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -2,7 +2,7 @@ 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 7f75b1dcf1..890c55b1cc 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 c6bacf485d..9bb6a16001 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 @@ def _mutate(self) -> Dict: 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 e1c78c1eb0..2a38ce323b 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 @@ def _mutate(self) -> Dict: # 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 67% rename from slither/tools/mutator/mutators/RCR.py rename to slither/tools/mutator/mutators/RR.py index 96aebc68f9..95cbf617a7 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 @@ def _mutate(self) -> Dict: 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 91c05b884e..9e9afc1e5f 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 671ee676d5..aac4b02a64 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 @@ def _mutate(self) -> Dict: 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 9aa81a0fc4..21925317dd 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.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 d61bba58af..01a142c8d0 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 0000000000..39c77f6731 --- /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 65cf78c276..8525e28084 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -4,7 +4,7 @@ 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 24/78] 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 66c0941a6d..e576970f7f 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 3758306f3f..a5d7f5f7fc 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -3,8 +3,6 @@ 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 bd40ad6acd..edd5843860 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -7,6 +7,7 @@ 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 @@ def __init__( 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 @@ def __init__( 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 @@ def __init__( 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 8525e28084..2013858df2 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.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 25/78] 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 e576970f7f..80d025c970 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 61eed67b1f..11593ee372 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 @@ def _mutate(self) -> Dict: 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 e6fa414378..29a6dc6726 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -42,7 +42,8 @@ def _mutate(self) -> Dict: 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 5ca46950fe..6a5552a5f5 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -31,7 +31,8 @@ def _mutate(self) -> Dict: 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 1935c43e60..79a63a88fb 100644 --- a/slither/tools/mutator/mutators/CR.py +++ b/slither/tools/mutator/mutators/CR.py @@ -20,8 +20,9 @@ def _mutate(self) -> Dict: 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 a5d7f5f7fc..84bfebe227 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -24,11 +24,12 @@ def _mutate(self) -> Dict: 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 c9966f1bec..e8217e9355 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -36,20 +36,20 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 e6903a01e9..e14c85708f 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -29,8 +29,8 @@ def _mutate(self) -> Dict: 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 0217324e09..421f94a5e5 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -20,16 +20,14 @@ def _mutate(self) -> Dict: 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 c81182c432..4ae387d294 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -25,18 +25,18 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 890c55b1cc..68bc2f2d83 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -27,15 +27,16 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 9bb6a16001..4c1e91b324 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -20,8 +20,8 @@ def _mutate(self) -> Dict: 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 2a38ce323b..da75a592ab 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -33,9 +33,9 @@ def _mutate(self) -> Dict: 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 95cbf617a7..3aab255eca 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -20,9 +20,10 @@ def _mutate(self) -> Dict: 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 9e9afc1e5f..f6adfff845 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -56,18 +56,19 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 aac4b02a64..fa00b52ae7 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -29,23 +29,24 @@ def _mutate(self) -> Dict: 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 edd5843860..f11d69db1d 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 @@ def __init__( 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 @@ def __init__( 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 @@ def _mutate(self) -> Dict: """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 @@ def mutate(self) -> Tuple[int, int]: 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 @@ def mutate(self) -> Tuple[int, int]: # 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 2013858df2..8525e28084 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.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 26/78] 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 0000000000..11b0b7eb51 --- /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 80d025c970..b375e9558a 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 f11d69db1d..558a514513 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -3,7 +3,6 @@ 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 @@ def mutate(self) -> Tuple[int, int, List[int]]: 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 01a142c8d0..ffebee9fc9 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 27/78] 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 11b0b7eb51..c615b0b795 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 b375e9558a..7bd4f8d791 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -26,7 +26,7 @@ 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 28/78] 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 c615b0b795..30b83ac460 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 7bd4f8d791..13e78a30ec 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 11593ee372..0c7f906b38 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 @@ 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 29a6dc6726..551cf8c644 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 @@ 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 6a5552a5f5..b6a9ae749c 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 @@ 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 79a63a88fb..5c34416e9f 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 84bfebe227..847466611c 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 @@ 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 e8217e9355..29efe6502c 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 @@ 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 e14c85708f..a8fff1c31f 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 @@ 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 421f94a5e5..5920143499 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 4ae387d294..b562ba9b0b 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 68bc2f2d83..dcb5be2592 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 4c1e91b324..b482ab5661 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 da75a592ab..826b15a4ad 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 @@ 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 3aab255eca..5afe188928 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 f6adfff845..0e94329089 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 @@ 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 fa00b52ae7..cf62c21bd1 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 @@ 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 558a514513..ea331e7c5c 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 @@ 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 @@ def __init__( 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 @@ def mutate(self) -> Tuple[int, int, List[int]]: # 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 042b4fff70..358586688c 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 29/78] 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 30b83ac460..8af977b082 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 13e78a30ec..56582d6f54 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -4,14 +4,14 @@ 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 @@ ################################################################################### 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 @@ def __call__( output_mutators(checks) parser.exit() - # endregion ################################################################################### ################################################################################### @@ -130,46 +133,46 @@ def __call__( ################################################################################### ################################################################################### -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 0c7f906b38..00506a1bbb 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 @@ def _mutate(self) -> Dict: # 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 551cf8c644..0e7452594f 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: # 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 b6a9ae749c..9f8ca2a118 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 @@ def _mutate(self) -> Dict: # 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 5c34416e9f..2960282362 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 847466611c..4560db4da2 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 @@ def _mutate(self) -> Dict: 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 29efe6502c..f9ef874cd9 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: new_str, line_no[0] ) - return result diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index a8fff1c31f..21837d81e7 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 @@ def _mutate(self) -> Dict: # 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 5920143499..a10ce1f1d7 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 @@ def _mutate(self) -> Dict: 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 b562ba9b0b..678b3b7475 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -56,5 +56,4 @@ def _mutate(self) -> Dict: 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 dcb5be2592..c82f132d74 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -55,5 +55,4 @@ def _mutate(self) -> Dict: 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 b482ab5661..20447290aa 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 @@ def _mutate(self) -> Dict: 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 826b15a4ad..d59e7575a9 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 @@ def _mutate(self) -> Dict: 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 5afe188928..6bfd644e05 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -12,20 +12,14 @@ def _mutate(self) -> 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: + 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 0e94329089..bbdc631943 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 @@ "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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 cf62c21bd1..b7e8c81569 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 @@ def _mutate(self) -> Dict: 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 ea331e7c5c..c2f15cd748 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -11,24 +11,24 @@ 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 @@ def __init__( 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 @@ 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}") + 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 @@ def mutate(self) -> Tuple[int, int, List[int]]: # 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 21925317dd..852a8efc34 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.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.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 ffebee9fc9..d4474c3101 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -6,47 +6,49 @@ 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 39c77f6731..e50f44612b 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 8525e28084..5c75f0eb31 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 30/78] 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 56582d6f54..f0b5c88bce 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -11,7 +11,11 @@ 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 @@ ################################################################################### ################################################################################### + 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 @@ def __call__( output_mutators(checks) parser.exit() + # endregion ################################################################################### ################################################################################### @@ -133,7 +142,10 @@ def __call__( ################################################################################### ################################################################################### -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 00506a1bbb..0bf0fb2a29 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -9,20 +9,23 @@ 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 @@ def _mutate(self) -> Dict: 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 0e7452594f..2ff403b386 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 @@ 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 @@ def _mutate(self) -> Dict: 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 9f8ca2a118..a8720a4b63 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -8,9 +8,10 @@ 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 @@ def _mutate(self) -> Dict: 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 2960282362..ebf93bf18a 100644 --- a/slither/tools/mutator/mutators/CR.py +++ b/slither/tools/mutator/mutators/CR.py @@ -6,14 +6,20 @@ 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 @@ def _mutate(self) -> Dict: 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 4560db4da2..028c1916cd 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -7,27 +7,36 @@ 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 f9ef874cd9..066a1fbb0e 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -7,16 +7,19 @@ 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 @@ def _mutate(self) -> Dict: # pylint: disable=too-many-branches 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 @@ def _mutate(self) -> Dict: # pylint: disable=too-many-branches 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 @@ def _mutate(self) -> Dict: # pylint: disable=too-many-branches 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 @@ def _mutate(self) -> Dict: # pylint: disable=too-many-branches 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 21837d81e7..2d1535b1aa 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -8,6 +8,7 @@ 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 @@ def _mutate(self) -> Dict: 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 a10ce1f1d7..f29569f63e 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -4,6 +4,7 @@ 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 @@ def _mutate(self) -> Dict: # 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 678b3b7475..4d5f6205d5 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -4,6 +4,7 @@ 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 c82f132d74..f9e51c5533 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -4,6 +4,7 @@ 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 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 20447290aa..9682f10caf 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -4,6 +4,7 @@ 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 @@ def _mutate(self) -> Dict: 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 d59e7575a9..9daae0663f 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -12,6 +12,7 @@ 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 @@ def _mutate(self) -> Dict: 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 6bfd644e05..e285d7a3f4 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -3,23 +3,36 @@ 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 bbdc631943..770b57180d 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -6,29 +6,29 @@ 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 @@ "(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 b7e8c81569..f427c2fbf6 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -8,9 +8,10 @@ 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 c2f15cd748..12c6b22983 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -9,17 +9,22 @@ 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 @@ def __init__( # pylint: disable=too-many-arguments 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 @@ def mutate(self) -> Tuple[int, int, List[int]]: (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 @@ def mutate(self) -> Tuple[int, int, List[int]]: 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 852a8efc34..b02a2cc9b9 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 358586688c..79d7050972 100644 --- a/slither/tools/mutator/utils/command_line.py +++ b/slither/tools/mutator/utils/command_line.py @@ -2,6 +2,7 @@ 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 d4474c3101..ddb3efb50a 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -6,6 +6,7 @@ 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 e50f44612b..54ff81e60b 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 5c75f0eb31..0e495f8ae6 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -10,6 +10,7 @@ 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 31/78] 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 7c81266bf6..9b8ae3f032 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -22,6 +22,7 @@ SOLIDITY_VARIABLES_COMPOSED = { "block.basefee": "uint", + "block.blobbasefee": "uint256", "block.coinbase": "address", "block.difficulty": "uint256", "block.prevrandao": "uint256", @@ -44,6 +45,8 @@ } 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 28ea70e933..11f79b4ce7 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 @@ "EXTCODECOPY", "RETURNDATASIZE", "RETURNDATACOPY", + "MCOPY", "EXTCODEHASH", "BLOCKHASH", "COINBASE", @@ -55,12 +56,16 @@ "GASLIMIT", "CHAINID", "SELFBALANCE", + "BLOBHASH", + "BLOBBASEFEE", "POP", "MLOAD", "MSTORE", "MSTORE8", "SLOAD", "SSTORE", + "TLOAD", + "TSTORE", "JUMP", "JUMPI", "PC", @@ -183,11 +188,15 @@ "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 @@ "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 32/78] 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 9b8ae3f032..86bdb5bd21 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -21,7 +21,7 @@ } 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 11f79b4ce7..23df6e85fb 100644 --- a/slither/solc_parsing/yul/evm_functions.py +++ b/slither/solc_parsing/yul/evm_functions.py @@ -56,6 +56,7 @@ "GASLIMIT", "CHAINID", "SELFBALANCE", + "BASEFEE", "BLOBHASH", "BLOBBASEFEE", "POP", @@ -195,6 +196,7 @@ "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 33/78] 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 86bdb5bd21..2d77a20c04 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -45,7 +45,6 @@ } 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 34/78] 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 f0b5c88bce..5c13d7aeae 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 @@ def __call__( ################################################################################### -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 066a1fbb0e..cc58cbae16 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -27,12 +27,8 @@ def _mutate(self) -> Dict: # pylint: disable=too-many-branches 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 4d5f6205d5..ce51792ffc 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -40,9 +40,7 @@ def _mutate(self) -> Dict: 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 770b57180d..efbda48774 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -71,9 +71,7 @@ def _mutate(self) -> Dict: 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 @@ def _mutate(self) -> Dict: 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 12c6b22983..375af1e6fd 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -104,9 +104,7 @@ def mutate(self) -> Tuple[int, int, List[int]]: 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 0e495f8ae6..6104cdd8a9 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 35/78] 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 6104cdd8a9..4c51b7e5af 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 36/78] 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 4a646bb42d..9675b0d359 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 37/78] 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 e0ab4b5434..dd63b5f478 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 38/78] 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 6017255b26..082333f2fc 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 9675b0d359..dbde094890 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 e28c7136a7..3d5eeed65d 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 0a0eb896de..555452871f 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 5415b6d1be..45dc0d8c28 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 a98f6ab58b..1c0a1d40ad 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 dd63b5f478..7fc17804cb 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 7e990371ff..091da2b968 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 1660a25e9c..68a32f80a9 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 39/78] 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 334da592c0..1f6ccd87e1 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 40/78] 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 59940ec1cd..c1b94661d1 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -1106,11 +1106,13 @@ def _parse_unchecked_block(self, block: Dict, node: NodeSolc, scope): 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 41/78] 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 1f8cb52f9c..f0af978ec7 100644 --- a/slither/detectors/functions/suicidal.py +++ b/slither/detectors/functions/suicidal.py @@ -59,7 +59,7 @@ def detect_suicidal_func(func: FunctionContract) -> bool: 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 4a784217df..99a6a0295f 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 428c794d4d..31b22d767a 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 42/78] 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 3d5eeed65d..4292d5f444 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 43/78] 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 dbde094890..7972c96e77 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 44/78] 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 7fc17804cb..72b002d1e7 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 45/78] 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 4292d5f444..0942afb6dd 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 46/78] 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 4411e3505c..170df8cba9 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 bc57dc51b5..e233fa993b 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -448,6 +448,7 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]: 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 0000000000..43eca2c9a9 --- /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 0000000000..33bbc74cdc --- /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 47/78] 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 d1b36d951b..3cd914a87a 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 747d2207ef..a3cc644042 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -135,7 +135,9 @@ def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None: 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 6c50fcab93..2432a21165 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -70,6 +70,7 @@ class FailOnLevel(enum.Enum): "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 48/78] 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 37f678d7a1..769ac58aa5 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 f5f0a98d9d..bd5a6d8449 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 a1591d834b..a1ad9c87e9 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 af7cbe2c77..c3290624be 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 49/78] 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 85921ce742..de8725b94d 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -456,9 +456,12 @@ def parse_contracts(self) -> None: # pylint: disable=too-many-statements,too-ma # 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 50/78] 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 de8725b94d..21dbfff708 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -458,7 +458,9 @@ def parse_contracts(self) -> None: # pylint: disable=too-many-statements,too-ma 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 51/78] 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 06b68c2bcd..6f83e13f0b 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 52/78] 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 d67f570c0a..b33fb9c5f7 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 @@ def __init__(self, field_names: List[str], pretty_align: bool = True): # TODO: 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 53/78] 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 72b002d1e7..234e2eb050 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 68a32f80a9..d677218410 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 54/78] 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 ac620c8e69..7895090805 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 55/78] 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 7895090805..02fb82f65c 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 d677218410..f91243cc7d 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 56/78] 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 10837bb4b0..b5e5c911a3 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 57/78] 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 39b1eacdac..0244dd6c67 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 58/78] 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 6f83e13f0b..2057782a4b 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 59/78] 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 6221fd8bdc..df652dab0c 100644 --- a/slither/core/compilation_unit.py +++ b/slither/core/compilation_unit.py @@ -302,10 +302,7 @@ def compute_storage_layout(self) -> None: 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 5403d227ad..7224859c63 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -436,6 +436,33 @@ def state_variables(self) -> List["StateVariable"]: """ 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 f9ef190246..63d1a7a838 100644 --- a/slither/core/variables/variable.py +++ b/slither/core/variables/variable.py @@ -93,6 +93,13 @@ def is_constant(self) -> bool: 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 0e73ab57b6..5771d96303 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 @@ def detect(self) -> None: 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 3325b7a010..0d8ce2612c 100644 --- a/slither/printers/summary/variable_order.py +++ b/slither/printers/summary/variable_order.py @@ -28,10 +28,9 @@ def output(self, _filename: str) -> Output: 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 8c0cf515d9..728636f2e4 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -398,7 +398,7 @@ def get_all_storage_variables(self, func: Callable = lambda x: x) -> None: 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 b4535ddfe3..b86036c87f 100644 --- a/slither/tools/upgradeability/checks/variable_initialization.py +++ b/slither/tools/upgradeability/checks/variable_initialization.py @@ -43,8 +43,8 @@ class VariableWithInit(AbstractCheck): 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 002559b6ea..fce0a09bb3 100644 --- a/slither/tools/upgradeability/checks/variables_order.py +++ b/slither/tools/upgradeability/checks/variables_order.py @@ -115,16 +115,8 @@ def _contract2(self) -> Contract: 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 @@ def _contract2(self) -> Contract: 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 288b581505..86e26cdbe2 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 bbb253175e..e8300ba84e 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 60/78] 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 bc57dc51b5..18793d54dd 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -21,12 +21,18 @@ # 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 @@ def __init__(self, test_file: str, solc_versions: List[str], disable_legacy: boo ) < 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 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]: 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 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]: 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 0000000000..be308dd12e --- /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 0000000000..eb96f5d28e --- /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 61/78] 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 c1b94661d1..5698f7b264 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -996,7 +996,9 @@ def _parse_statement( 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 62/78] 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 0000000000..9681e32642 --- /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 1f6a878e2f..93ac6b799d 100644 --- a/slither/detectors/assembly/shift_parameter_mixup.py +++ b/slither/detectors/assembly/shift_parameter_mixup.py @@ -8,6 +8,7 @@ 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 @@ class ShiftParameterMixup(AbstractDetector): 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 354d90a138..81b72456ca 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 1c4206ea0f..09e4a60c94 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 89a9210ad8..9681e32642 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 11a2af9ae3..9681e32642 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 63/78] 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 bafe8a53d1..7a501dac68 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 09c0a51f79..344d6e29cd 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 09c0a51f79..344d6e29cd 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 8f6ef922b6..cdc7d7458d 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 a9569a2fb2..afbb84ed7c 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 915f1d3c4a..081b6acd51 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 915f1d3c4a..081b6acd51 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 64/78] 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 21dbfff708..d67847a531 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -421,66 +421,56 @@ def parse_contracts(self) -> None: # pylint: disable=too-many-statements,too-ma 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 0000000000..6f1429e914 --- /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 0000000000..dd85ad3dd7 --- /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 0000000000..722acdd219 --- /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 0000000000..a34f15ed4a --- /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 65/78] 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 a34f15ed4a..d3702e2a53 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 66/78] 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 23c82cae11..5edbe49238 100644 --- a/examples/scripts/data_dependency.py +++ b/examples/scripts/data_dependency.py @@ -126,3 +126,17 @@ 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 a4f64870af..b4baf5c090 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 67/78] 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 9681e32642..0000000000 --- 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 68/78] 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 fce0a09bb3..8d525a6dd3 100644 --- a/slither/tools/upgradeability/checks/variables_order.py +++ b/slither/tools/upgradeability/checks/variables_order.py @@ -115,8 +115,8 @@ def _contract2(self) -> Contract: 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 @@ def _contract2(self) -> Contract: 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 e8300ba84e..dd7bfe4656 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 d592e76dea61bea5c65c77b1fef968e023ddf109 Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 20 Feb 2024 19:46:09 +0100 Subject: [PATCH 69/78] Track storage variables read/written in assembly --- slither/core/cfg/node.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/slither/core/cfg/node.py b/slither/core/cfg/node.py index 9b53b0db92..87d0e16a2e 100644 --- a/slither/core/cfg/node.py +++ b/slither/core/cfg/node.py @@ -11,6 +11,7 @@ SolidityFunction, ) from slither.core.expressions.expression import Expression +from slither.core.expressions import CallExpression, Identifier, AssignmentOperation from slither.core.solidity_types import ElementaryType from slither.core.source_mapping.source_mapping import SourceMapping from slither.core.variables.local_variable import LocalVariable @@ -898,6 +899,21 @@ def _find_read_write_call(self) -> None: # pylint: disable=too-many-statements # TODO: consider removing dependancy of solidity_call to internal_call self._solidity_calls.append(ir.function) self._internal_calls.append(ir.function) + if ( + isinstance(ir, SolidityCall) + and ir.function == SolidityFunction("sstore(uint256,uint256)") + and isinstance(ir.node.expression, CallExpression) + and isinstance(ir.node.expression.arguments[0], Identifier) + ): + self._vars_written.append(ir.arguments[0]) + if ( + isinstance(ir, SolidityCall) + and ir.function == SolidityFunction("sload(uint256)") + and isinstance(ir.node.expression, AssignmentOperation) + and isinstance(ir.node.expression.expression_right, CallExpression) + and isinstance(ir.node.expression.expression_right.arguments[0], Identifier) + ): + self._vars_read.append(ir.arguments[0]) if isinstance(ir, LowLevelCall): assert isinstance(ir.destination, (Variable, SolidityVariable)) self._low_level_calls.append((ir.destination, str(ir.function_name.value))) 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 70/78] 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 e0e303ed84..29f0ac2e02 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 }} From a9163d2a7948915b4641763cc077aa7fb8c5dece Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 20 Feb 2024 22:46:28 +0100 Subject: [PATCH 71/78] Add --include-paths option --- slither/__main__.py | 35 +++++++++++++++++++++++------------ slither/core/slither_core.py | 22 +++++++++++++++++----- slither/slither.py | 4 ++++ slither/utils/command_line.py | 1 + 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/slither/__main__.py b/slither/__main__.py index 3cd914a87a..405eb9142d 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -268,9 +268,10 @@ def choose_printers( ################################################################################### -def parse_filter_paths(args: argparse.Namespace) -> List[str]: - if args.filter_paths: - return args.filter_paths.split(",") +def parse_filter_paths(args: argparse.Namespace, filter: bool) -> List[str]: + paths = args.filter_paths if filter else args.include_paths + if paths: + return paths.split(",") return [] @@ -307,6 +308,7 @@ def parse_args( "Checklist (consider using https://github.com/crytic/slither-action)" ) group_misc = parser.add_argument_group("Additional options") + group_filters = parser.add_mutually_exclusive_group() group_detector.add_argument( "--detect", @@ -518,14 +520,6 @@ def parse_args( default=defaults_flag_in_config["disable_color"], ) - group_misc.add_argument( - "--filter-paths", - help="Regex filter to exclude detector results matching file path e.g. (mocks/|test/)", - action="store", - dest="filter_paths", - default=defaults_flag_in_config["filter_paths"], - ) - group_misc.add_argument( "--triage-mode", help="Run triage mode (save results in triage database)", @@ -579,6 +573,22 @@ def parse_args( default=defaults_flag_in_config["no_fail"], ) + group_filters.add_argument( + "--filter-paths", + help="Regex filter to exclude detector results matching file path e.g. (mocks/|test/)", + action="store", + dest="filter_paths", + default=defaults_flag_in_config["filter_paths"], + ) + + group_filters.add_argument( + "--include-paths", + help="Regex filter to include detector results matching file path e.g. (mocks/|test/)", + action="store", + dest="include_paths", + default=defaults_flag_in_config["include_paths"], + ) + codex.init_parser(parser) # debugger command @@ -631,7 +641,8 @@ def parse_args( args = parser.parse_args() read_config_file(args) - args.filter_paths = parse_filter_paths(args) + args.filter_paths = parse_filter_paths(args, True) + args.include_paths = parse_filter_paths(args, False) # Verify our json-type output is valid args.json_types = set(args.json_types.split(",")) # type:ignore diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py index b1bb7c66b8..76220f5bae 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -62,6 +62,7 @@ def __init__(self) -> None: # Multiple time the same result, so we remove duplicates self._currently_seen_resuts: Set[str] = set() self._paths_to_filter: Set[str] = set() + self._paths_to_include: Set[str] = set() self._crytic_compile: Optional[CryticCompile] = None @@ -411,25 +412,29 @@ def valid_result(self, r: Dict) -> bool: if "source_mapping" in elem ] - # Use POSIX-style paths so that filter_paths works across different + # Use POSIX-style paths so that filter_paths|include_paths works across different # OSes. Convert to a list so elements don't get consumed and are lost # while evaluating the first pattern source_mapping_elements = list( map(lambda x: pathlib.Path(x).resolve().as_posix() if x else x, source_mapping_elements) ) - matching = False + (matching, paths, msg_err) = ( + (True, self._paths_to_include, "--include-paths") + if self._paths_to_include + else (False, self._paths_to_filter, "--filter-paths") + ) - for path in self._paths_to_filter: + for path in paths: try: if any( bool(re.search(_relative_path_format(path), src_mapping)) for src_mapping in source_mapping_elements ): - matching = True + matching = not matching break except re.error: logger.error( - f"Incorrect regular expression for --filter-paths {path}." + f"Incorrect regular expression for {msg_err} {path}." "\nSlither supports the Python re format" ": https://docs.python.org/3/library/re.html" ) @@ -500,6 +505,13 @@ def add_path_to_filter(self, path: str): """ self._paths_to_filter.add(path) + def add_path_to_include(self, path: str): + """ + Add path to include + Path are used through direct comparison (no regex) + """ + self._paths_to_include.add(path) + # endregion ################################################################################### ################################################################################### diff --git a/slither/slither.py b/slither/slither.py index a3cc644042..4259b74b71 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -132,6 +132,10 @@ def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None: for p in filter_paths: self.add_path_to_filter(p) + include_paths = kwargs.get("include_paths", []) + for p in include_paths: + self.add_path_to_include(p) + self._exclude_dependencies = kwargs.get("exclude_dependencies", False) triage_mode = kwargs.get("triage_mode", False) diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index 2432a21165..f03ced8345 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -60,6 +60,7 @@ class FailOnLevel(enum.Enum): "json-types": ",".join(DEFAULT_JSON_OUTPUT_TYPES), "disable_color": False, "filter_paths": None, + "include_paths": None, "generate_patches": False, # debug command "skip_assembly": False, From c0d4dde29958dd0a35a6b2c11f3ecf135f3d42f8 Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 20 Feb 2024 22:51:04 +0100 Subject: [PATCH 72/78] Lint --- slither/__main__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slither/__main__.py b/slither/__main__.py index 405eb9142d..25d83355fe 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -268,8 +268,8 @@ def choose_printers( ################################################################################### -def parse_filter_paths(args: argparse.Namespace, filter: bool) -> List[str]: - paths = args.filter_paths if filter else args.include_paths +def parse_filter_paths(args: argparse.Namespace, filter_path: bool) -> List[str]: + paths = args.filter_paths if filter_path else args.include_paths if paths: return paths.split(",") return [] From 665b630f489afb3f84ea85a7c401d7b504a7b174 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 21 Feb 2024 09:57:57 -0600 Subject: [PATCH 73/78] fix: support inheritance resolution when contract name is reused --- .../slither_compilation_unit_solc.py | 25 +++++++++++++------ .../contract_with_duplicate_names.sol | 0 .../duplicate_names}/import.sol | 0 .../renaming}/a.sol | 0 .../renaming}/b.sol | 0 .../renaming}/c.sol | 0 tests/unit/core/test_error_messages.py | 18 ------------- tests/unit/core/test_inheritance.py | 15 ++++++++--- 8 files changed, 29 insertions(+), 29 deletions(-) rename tests/unit/core/test_data/{inheritance_resolution_error => inheritance_resolution/duplicate_names}/contract_with_duplicate_names.sol (100%) rename tests/unit/core/test_data/{inheritance_resolution_error => inheritance_resolution/duplicate_names}/import.sol (100%) rename tests/unit/core/test_data/{inheritance_with_renaming => inheritance_resolution/renaming}/a.sol (100%) rename tests/unit/core/test_data/{inheritance_with_renaming => inheritance_resolution/renaming}/b.sol (100%) rename tests/unit/core/test_data/{inheritance_with_renaming => inheritance_resolution/renaming}/c.sol (100%) delete mode 100644 tests/unit/core/test_error_messages.py diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 2b96eb0d48..f2867aaac5 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -434,17 +434,28 @@ def parse_contracts(self) -> None: # pylint: disable=too-many-statements,too-ma 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[ + target = None + # For contracts that are imported and aliased e.g. 'import {A as B} from "./C.sol"', + # we look through the imports's (`Import`) renaming to find the original contract name + # and then look up the original contract in the import path's scope (`FileScope`). + for import_ in contract_parser.underlying_contract.file_scope.imports: + if contract_name in import_.renaming: + target = self.compilation_unit.get_scope( + import_.filename + ).get_contract_from_name(import_.renaming[contract_name]) + + # Fallback to the current file scope if the contract is not found in the import path's scope. + # It is assumed that it isn't possible to defined a contract with the same name as "aliased" names. + if target is None: + target = contract_parser.underlying_contract.file_scope.get_contract_from_name( 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." + f"\n Try changing `contract {target}` ({target.source_mapping}) to a unique name as a workaround." + "\n Please share the source code that caused this error here: https://github.com/crytic/slither/issues/" ) assert target, f"Contract {contract_name} not found" return target diff --git a/tests/unit/core/test_data/inheritance_resolution_error/contract_with_duplicate_names.sol b/tests/unit/core/test_data/inheritance_resolution/duplicate_names/contract_with_duplicate_names.sol similarity index 100% rename from tests/unit/core/test_data/inheritance_resolution_error/contract_with_duplicate_names.sol rename to tests/unit/core/test_data/inheritance_resolution/duplicate_names/contract_with_duplicate_names.sol diff --git a/tests/unit/core/test_data/inheritance_resolution_error/import.sol b/tests/unit/core/test_data/inheritance_resolution/duplicate_names/import.sol similarity index 100% rename from tests/unit/core/test_data/inheritance_resolution_error/import.sol rename to tests/unit/core/test_data/inheritance_resolution/duplicate_names/import.sol diff --git a/tests/unit/core/test_data/inheritance_with_renaming/a.sol b/tests/unit/core/test_data/inheritance_resolution/renaming/a.sol similarity index 100% rename from tests/unit/core/test_data/inheritance_with_renaming/a.sol rename to tests/unit/core/test_data/inheritance_resolution/renaming/a.sol diff --git a/tests/unit/core/test_data/inheritance_with_renaming/b.sol b/tests/unit/core/test_data/inheritance_resolution/renaming/b.sol similarity index 100% rename from tests/unit/core/test_data/inheritance_with_renaming/b.sol rename to tests/unit/core/test_data/inheritance_resolution/renaming/b.sol diff --git a/tests/unit/core/test_data/inheritance_with_renaming/c.sol b/tests/unit/core/test_data/inheritance_resolution/renaming/c.sol similarity index 100% rename from tests/unit/core/test_data/inheritance_with_renaming/c.sol rename to tests/unit/core/test_data/inheritance_resolution/renaming/c.sol diff --git a/tests/unit/core/test_error_messages.py b/tests/unit/core/test_error_messages.py deleted file mode 100644 index d0d915d56a..0000000000 --- a/tests/unit/core/test_error_messages.py +++ /dev/null @@ -1,18 +0,0 @@ -from pathlib import Path -import pytest - - -from slither import Slither -from slither.solc_parsing.slither_compilation_unit_solc import InheritanceResolutionError - -TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" -INHERITANCE_ERROR_ROOT = Path(TEST_DATA_DIR, "inheritance_resolution_error") - - -def test_inheritance_resolution_error(solc_binary_path) -> None: - with pytest.raises(InheritanceResolutionError): - solc_path = solc_binary_path("0.8.0") - Slither( - Path(INHERITANCE_ERROR_ROOT, "contract_with_duplicate_names.sol").as_posix(), - solc=solc_path, - ) diff --git a/tests/unit/core/test_inheritance.py b/tests/unit/core/test_inheritance.py index d3702e2a53..80a0082a72 100644 --- a/tests/unit/core/test_inheritance.py +++ b/tests/unit/core/test_inheritance.py @@ -4,14 +4,13 @@ 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" +TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" / "inheritance_resolution" # https://github.com/crytic/slither/issues/2304 def test_inheritance_with_renaming(solc_binary_path) -> None: - solc_path = solc_binary_path("0.8.15") + solc_path = solc_binary_path("0.8.0") standard_json = SolcStandardJson() - for source_file in Path(TEST_DATA_DIR).rglob("*.sol"): - print(source_file) + for source_file in Path(TEST_DATA_DIR / "renaming").rglob("*.sol"): standard_json.add_source_file(Path(source_file).as_posix()) compilation = CryticCompile(standard_json, solc=solc_path) slither = Slither(compilation) @@ -34,3 +33,11 @@ def test_inheritance_with_renaming(solc_binary_path) -> None: assert len(b.immediate_inheritance) == 1 assert b.immediate_inheritance[0] == c assert len(b.explicit_base_constructor_calls) == 0 + + +def test_inheritance_with_duplicate_names(solc_binary_path) -> None: + solc_path = solc_binary_path("0.8.0") + Slither( + Path(TEST_DATA_DIR / "duplicate_names", "contract_with_duplicate_names.sol").as_posix(), + solc=solc_path, + ) From 69d3c257b4285c0935c797ff99f52cb44448564e Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 28 Feb 2024 17:36:49 -0600 Subject: [PATCH 74/78] feat: add out-of-order-retryable ticket detector --- slither/detectors/all_detectors.py | 3 + .../functions/out_of_order_retryable.py | 143 ++++++++++++++++++ ...e_0_8_20_out_of_order_retryable_sol__0.txt | 8 + .../0.8.20/out_of_order_retryable.sol | 82 ++++++++++ .../out_of_order_retryable.sol-0.8.20.zip | Bin 0 -> 5285 bytes tests/e2e/detectors/test_detectors.py | 5 + 6 files changed, 241 insertions(+) create mode 100644 slither/detectors/functions/out_of_order_retryable.py create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt create mode 100644 tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol create mode 100644 tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol-0.8.20.zip diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index fab9562d20..fc33ddfd38 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -97,3 +97,6 @@ from .operations.incorrect_exp import IncorrectOperatorExponentiation from .statements.tautological_compare import TautologicalCompare from .statements.return_bomb import ReturnBomb + + +from .functions.out_of_order_retryable import OutOfOrderRetryable diff --git a/slither/detectors/functions/out_of_order_retryable.py b/slither/detectors/functions/out_of_order_retryable.py new file mode 100644 index 0000000000..b273052fef --- /dev/null +++ b/slither/detectors/functions/out_of_order_retryable.py @@ -0,0 +1,143 @@ +from typing import List + +from slither.core.cfg.node import Node +from slither.core.declarations import Function, FunctionContract +from slither.slithir.operations import HighLevelCall +from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification +from slither.utils.output import Output + + +class OutOfOrderRetryable(AbstractDetector): + + ARGUMENT = "out-of-order-retryable" + HELP = "Out-of-order retryable transactions" + IMPACT = DetectorClassification.MEDIUM + CONFIDENCE = DetectorClassification.MEDIUM + + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#out-of-order-retryable-transactions" + + WIKI_TITLE = "Out-of-order retryable transactions" + WIKI_DESCRIPTION = "Out-of-order retryable transactions" + + # region wiki_exploit_scenario + WIKI_EXPLOIT_SCENARIO = """ +```solidity +contract L1 { + function doStuffOnL2() external { + // Retryable A + IInbox(inbox).createRetryableTicket({ + to: l2contract, + l2CallValue: 0, + maxSubmissionCost: maxSubmissionCost, + excessFeeRefundAddress: msg.sender, + callValueRefundAddress: msg.sender, + gasLimit: gasLimit, + maxFeePerGas: maxFeePerGas, + data: abi.encodeCall(l2contract.claim_rewards, ()) + }); + // Retryable B + IInbox(inbox).createRetryableTicket({ + to: l2contract, + l2CallValue: 0, + maxSubmissionCost: maxSubmissionCost, + excessFeeRefundAddress: msg.sender, + callValueRefundAddress: msg.sender, + gasLimit: gas, + maxFeePerGas: maxFeePerGas, + data: abi.encodeCall(l2contract.unstake, ()) + }); + } +} + +contract L2 { + function claim_rewards() public { + // rewards is computed based on balance and staking period + uint unclaimed_rewards = _compute_and_update_rewards(); + token.safeTransfer(msg.sender, unclaimed_rewards); + } + + // Call claim_rewards before unstaking, otherwise you lose your rewards + function unstake() public { + _free_rewards(); // clean up rewards related variables + balance = balance[msg.sender]; + balance[msg.sender] = 0; + staked_token.safeTransfer(msg.sender, balance); + } +} +``` +Bob calls `doStuffOnL2` but the first retryable ticket calling `claim_rewards` fails. The second retryable ticket calling `unstake` is executed successfully. As a result, Bob loses his rewards.""" + # endregion wiki_exploit_scenario + + WIKI_RECOMMENDATION = "Do not rely on the order or successful execution of retryable tickets." + + key = "OUTOFORDERRETRYABLE" + + def _detect_multiple_tickets( + self, function: FunctionContract, node: Node, visited: List[Node] + ) -> None: + if node in visited: + return + + visited = visited + [node] + + fathers_context = [] + + for father in node.fathers: + if self.key in father.context: + fathers_context += father.context[self.key] + + # Exclude path that dont bring further information + if node in self.visited_all_paths: + if all(f_c in self.visited_all_paths[node] for f_c in fathers_context): + return + else: + self.visited_all_paths[node] = [] + + self.visited_all_paths[node] = self.visited_all_paths[node] + fathers_context + + if self.key not in node.context: + node.context[self.key] = fathers_context + + # analyze node + for ir in node.irs: + if ( + isinstance(ir, HighLevelCall) + and isinstance(ir.function, Function) + and ir.function.name == "createRetryableTicket" + ): + node.context[self.key].append(node) + + if len(node.context[self.key]) > 1: + self.results.append(node.context[self.key]) + return + + for son in node.sons: + self._detect_multiple_tickets(function, son, visited) + + def _detect(self) -> List[Output]: + results = [] + + # pylint: disable=attribute-defined-outside-init + self.results = [] + self.visited_all_paths = {} + + for contract in self.compilation_unit.contracts: + for function in contract.functions: + if ( + function.is_implemented + and function.contract_declarer == contract + and function.entry_point + ): + function.entry_point.context[self.key] = [] + self._detect_multiple_tickets(function, function.entry_point, []) + + for multiple_tickets in self.results: + info = ["Multiple retryable tickets created in the same function:\n"] + + for x in multiple_tickets: + info += ["\t -", x, "\n"] + + json = self.generate_result(info) + results.append(json) + + return results diff --git a/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt new file mode 100644 index 0000000000..4f07601b1b --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt @@ -0,0 +1,8 @@ +Multiple retryable tickets created in the same function: + -Y(msg.sender).createRetryableTicket(address(1),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#62-70) + -Y(msg.sender).createRetryableTicket(address(2),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#72-80) + +Multiple retryable tickets created in the same function: + -Y(msg.sender).createRetryableTicket(address(1),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#40-48) + -Y(msg.sender).createRetryableTicket(address(2),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#50-58) + diff --git a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol new file mode 100644 index 0000000000..afd4d274b8 --- /dev/null +++ b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol @@ -0,0 +1,82 @@ +interface Y { + function createRetryableTicket( + address to, + uint256 l2CallValue, + uint256 maxSubmissionCost, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, + bytes calldata data + ) external payable returns (uint256); +} + +contract X { +function good() external { + if (true) { + Y(msg.sender).createRetryableTicket( + address(1), + 0, + 0, + address(0), + address(0), + 0, + 0, + ""); + } else { + Y(msg.sender).createRetryableTicket( + address(2), + 0, + 0, + address(0), + address(0), + 0, + 0, + ""); + } +} +function bad1() external { + if (true) { + Y(msg.sender).createRetryableTicket( + address(1), + 0, + 0, + address(0), + address(0), + 0, + 0, + ""); + } + Y(msg.sender).createRetryableTicket( + address(2), + 0, + 0, + address(0), + address(0), + 0, + 0, + ""); + +} +function bad2() external { + Y(msg.sender).createRetryableTicket( + address(1), + 0, + 0, + address(0), + address(0), + 0, + 0, + ""); + + Y(msg.sender).createRetryableTicket( + address(2), + 0, + 0, + address(0), + address(0), + 0, + 0, + ""); +} +} \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol-0.8.20.zip b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol-0.8.20.zip new file mode 100644 index 0000000000000000000000000000000000000000..1baadba84d201e0a4cecf23dae4f0c2af3f8445c GIT binary patch literal 5285 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 Date: Wed, 28 Feb 2024 17:58:10 -0600 Subject: [PATCH 75/78] make it interprocedural (only 1 call deep) --- slither/detectors/all_detectors.py | 2 -- .../functions/out_of_order_retryable.py | 17 ++++++++++--- ...e_0_8_20_out_of_order_retryable_sol__0.txt | 4 +++ .../0.8.20/out_of_order_retryable.sol | 23 ++++++++++++++++++ .../out_of_order_retryable.sol-0.8.20.zip | Bin 5285 -> 5942 bytes 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index fc33ddfd38..4151759f0d 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -97,6 +97,4 @@ from .operations.incorrect_exp import IncorrectOperatorExponentiation from .statements.tautological_compare import TautologicalCompare from .statements.return_bomb import ReturnBomb - - from .functions.out_of_order_retryable import OutOfOrderRetryable diff --git a/slither/detectors/functions/out_of_order_retryable.py b/slither/detectors/functions/out_of_order_retryable.py index b273052fef..f483dc64aa 100644 --- a/slither/detectors/functions/out_of_order_retryable.py +++ b/slither/detectors/functions/out_of_order_retryable.py @@ -98,12 +98,23 @@ def _detect_multiple_tickets( if self.key not in node.context: node.context[self.key] = fathers_context - # analyze node - for ir in node.irs: + # include ops from internal function calls + internal_ops = [] + for internal_call in node.internal_calls: + if isinstance(internal_call, Function): + internal_ops += internal_call.all_slithir_operations() + + # analyze node for retryable tickets + for ir in node.irs + internal_ops: if ( isinstance(ir, HighLevelCall) and isinstance(ir.function, Function) - and ir.function.name == "createRetryableTicket" + and ir.function.name + in [ + "createRetryableTicket", + "outboundTransferCustomRefund", + "unsafeCreateRetryableTicket", + ] ): node.context[self.key].append(node) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt index 4f07601b1b..a54b2240d3 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt @@ -6,3 +6,7 @@ Multiple retryable tickets created in the same function: -Y(msg.sender).createRetryableTicket(address(1),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#40-48) -Y(msg.sender).createRetryableTicket(address(2),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#50-58) +Multiple retryable tickets created in the same function: + -Y(msg.sender).createRetryableTicket(address(1),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#83-91) + -good2() (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#92) + diff --git a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol index afd4d274b8..af20814a57 100644 --- a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol +++ b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol @@ -79,4 +79,27 @@ function bad2() external { 0, ""); } +function bad3() external { + Y(msg.sender).createRetryableTicket( + address(1), + 0, + 0, + address(0), + address(0), + 0, + 0, + ""); + good2(); +} +function good2() internal { + Y(msg.sender).createRetryableTicket( + address(2), + 0, + 0, + address(0), + address(0), + 0, + 0, + ""); +} } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol-0.8.20.zip b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol-0.8.20.zip index 1baadba84d201e0a4cecf23dae4f0c2af3f8445c..604b64ae7a38a632dcaeafeae1bc773299210399 100644 GIT binary patch delta 5662 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 S004#slin6m1~U`@0000~g^O?i From 75c1159d7300e1eab9b924d83e69f415a964739f Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 29 Feb 2024 10:40:07 -0600 Subject: [PATCH 76/78] add test showing two internal call example is caught --- .../functions/out_of_order_retryable.py | 1 + ...e_0_8_20_out_of_order_retryable_sol__0.txt | 4 ++++ .../0.8.20/out_of_order_retryable.sol | 6 +++++- .../out_of_order_retryable.sol-0.8.20.zip | Bin 5942 -> 6058 bytes 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/slither/detectors/functions/out_of_order_retryable.py b/slither/detectors/functions/out_of_order_retryable.py index f483dc64aa..db9096f95f 100644 --- a/slither/detectors/functions/out_of_order_retryable.py +++ b/slither/detectors/functions/out_of_order_retryable.py @@ -72,6 +72,7 @@ class OutOfOrderRetryable(AbstractDetector): key = "OUTOFORDERRETRYABLE" + # pylint: disable=too-many-branches def _detect_multiple_tickets( self, function: FunctionContract, node: Node, visited: List[Node] ) -> None: diff --git a/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt index a54b2240d3..4b0371a8c2 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt @@ -2,6 +2,10 @@ Multiple retryable tickets created in the same function: -Y(msg.sender).createRetryableTicket(address(1),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#62-70) -Y(msg.sender).createRetryableTicket(address(2),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#72-80) +Multiple retryable tickets created in the same function: + -good2() (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#95) + -good2() (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#96) + Multiple retryable tickets created in the same function: -Y(msg.sender).createRetryableTicket(address(1),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#40-48) -Y(msg.sender).createRetryableTicket(address(2),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#50-58) diff --git a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol index af20814a57..e3f8feb2e4 100644 --- a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol +++ b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol @@ -90,7 +90,11 @@ function bad3() external { 0, ""); good2(); -} +} +function bad4() external { + good2(); + good2(); +} function good2() internal { Y(msg.sender).createRetryableTicket( address(2), diff --git a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol-0.8.20.zip b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol-0.8.20.zip index 604b64ae7a38a632dcaeafeae1bc773299210399..fd52cf1802ca8d58c5c02b660f1657cc9b69d2da 100644 GIT binary patch delta 5778 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 QX;_oq7E%T{7XSbN01k^cP5=M^ delta 5676 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 S0001QlV=w_2E-Ns0000emIV0# From 801a13e6004b3fdd66ea6689d823e5581dff29e7 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 29 Feb 2024 11:13:26 -0600 Subject: [PATCH 77/78] add regression test for https://github.com/crytic/slither/issues/2325 --- .../0.8.0/const_state_variables.sol | 9 +++++++-- .../0.8.0/const_state_variables.sol-0.8.0.zip | Bin 8365 -> 8993 bytes 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol b/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol index f405a15875..00b0955c85 100644 --- a/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol +++ b/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol @@ -66,7 +66,7 @@ contract Good { uint immutable should_be_immutable_3 = 10 + block.number; B immutable should_be_immutable_4 = new B(); uint immutable should_be_immutable_5; - + uint blobBaseFee; constructor(uint b) { should_be_immutable_5 = b; } @@ -74,5 +74,10 @@ contract Good { function getNumber() public returns(uint){ return block.number; } - + + function updateBlobBaseFee(uint _blobBaseFee) public { + assembly { + sstore(blobBaseFee.slot, _blobBaseFee) + } + } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol-0.8.0.zip b/tests/e2e/detectors/test_data/constable-states/0.8.0/const_state_variables.sol-0.8.0.zip index d04c3f8e79c1a87787c6abc5a9ca6fb901b42ddb..7afd3884bb35261471e4fb871c6da2a5f91b454f 100644 GIT binary patch delta 8759 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 Date: Thu, 29 Feb 2024 11:30:38 -0600 Subject: [PATCH 78/78] update --inlude-paths help --- slither/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/__main__.py b/slither/__main__.py index 25d83355fe..ee1428967b 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -583,7 +583,7 @@ def parse_args( group_filters.add_argument( "--include-paths", - help="Regex filter to include detector results matching file path e.g. (mocks/|test/)", + help="Regex filter to include detector results matching file path e.g. (src/|contracts/). Opposite of --filter-paths", action="store", dest="include_paths", default=defaults_flag_in_config["include_paths"],