Skip to content

Commit

Permalink
Scope imports only correct items
Browse files Browse the repository at this point in the history
  • Loading branch information
smonicas committed Sep 19, 2023
1 parent 1db0d01 commit 256ca32
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 22 deletions.
98 changes: 96 additions & 2 deletions slither/core/scope/scope.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Any, Dict, Optional, Union, Set, TypeVar, Callable
from typing import List, Any, Dict, Optional, Union, Set, TypeVar, Callable, Tuple

Check warning on line 1 in slither/core/scope/scope.py

View workflow job for this annotation

GitHub Actions / Lint Code Base

W0611: Unused Tuple imported from typing (unused-import)

from crytic_compile import CompilationUnit
from crytic_compile.source_unit import SourceUnit
Expand Down Expand Up @@ -27,7 +27,7 @@ def _dict_contain(d1: Dict, d2: Dict) -> bool:
class FileScope:
def __init__(self, filename: Filename) -> None:
self.filename = filename
self.accessible_scopes: List[FileScope] = []
self.accessible_scopes: List[FileScopeToImport] = []

self.contracts: Dict[str, Contract] = {}
# Custom error are a list instead of a dict
Expand Down Expand Up @@ -238,3 +238,97 @@ def __hash__(self) -> int:
return hash(self.filename.relative)

# endregion

class FileScopeToImport:
def __init__(self, filescope: FileScope, items_to_import: List[str]) -> None:
self.filescope = filescope
self.items_to_import = items_to_import

Check warning on line 246 in slither/core/scope/scope.py

View workflow job for this annotation

GitHub Actions / Lint Code Base

C0303: Trailing whitespace (trailing-whitespace)
@property
def contracts(self) -> Dict[str, Contract]:
if len(self.items_to_import) != 0:
result = {}
for name, contract in self.filescope.contracts.items():
if name in self.items_to_import:
result[name] = contract
return result
return self.filescope.contracts

@property
def custom_errors(self) -> Set[CustomErrorTopLevel]:
if len(self.items_to_import) != 0:
result = set()
for custom_error in self.filescope.custom_errors:
if custom_error.name in self.items_to_import:
result.add(custom_error)
return result
return self.filescope.custom_errors

@property
def enums(self) -> Dict[str, EnumTopLevel]:
if len(self.items_to_import) != 0:
result = {}
for name, enum in self.filescope.enums.items():
if name in self.items_to_import:
result[name] = enum
return result
return self.filescope.enums

@property
def functions(self) -> Set[FunctionTopLevel]:
if len(self.items_to_import) != 0:
result = set()
for function in self.filescope.functions:
if function.name in self.items_to_import:
result.add(function)
return result
return self.filescope.functions

@property
def using_for_directives(self) -> Set[UsingForTopLevel]:
# TODO check it's correct
if len(self.items_to_import) == 0:
return self.filescope.using_for_directives
return set()

Check warning on line 293 in slither/core/scope/scope.py

View workflow job for this annotation

GitHub Actions / Lint Code Base

C0303: Trailing whitespace (trailing-whitespace)
@property
def imports(self) -> Set[Import]:
# TODO check it's correct
if len(self.items_to_import) == 0:
return self.filescope.imports
return set()

@property
def pragmas(self) -> Set[Pragma]:
# TODO check it's correct
return self.filescope.pragmas

@property
def structures(self) -> Dict[str, StructureTopLevel]:
if len(self.items_to_import) != 0:
result = {}
for name, structure in self.filescope.structures.items():
if name in self.items_to_import:
result[name] = structure
return result
return self.filescope.structures

@property
def variables(self) -> Dict[str, TopLevelVariable]:
if len(self.items_to_import) != 0:
result = {}
for name, variable in self.filescope.variables.items():
if name in self.items_to_import:
result[name] = variable
return result
return self.filescope.variables

@property
def renaming(self) -> Dict[str, str]:
# TODO check it's correct
return self.filescope.renaming

@property
def type_aliases(self) -> Dict[str, TypeAlias]:
# TODO check it's correct
return self.filescope.type_aliases
44 changes: 24 additions & 20 deletions slither/solc_parsing/slither_compilation_unit_solc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from slither.core.declarations.pragma_directive import Pragma
from slither.core.declarations.structure_top_level import StructureTopLevel
from slither.core.declarations.using_for_top_level import UsingForTopLevel
from slither.core.scope.scope import FileScope
from slither.core.scope.scope import FileScope, FileScopeToImport
from slither.core.solidity_types import ElementaryType, TypeAliasTopLevel
from slither.core.variables.top_level_variable import TopLevelVariable
from slither.exceptions import SlitherException
Expand All @@ -39,7 +39,7 @@ class InheritanceResolutionError(SlitherException):

def _handle_import_aliases(
symbol_aliases: Dict, import_directive: Import, scope: FileScope
) -> None:
) -> List[str]:
"""
Handle the parsing of import aliases
Expand All @@ -51,24 +51,27 @@ def _handle_import_aliases(
Returns:
"""
to_import = []
for symbol_alias in symbol_aliases:
if "foreign" in symbol_alias and "local" in symbol_alias:
if isinstance(symbol_alias["foreign"], dict) and "name" in symbol_alias["foreign"]:

original_name = symbol_alias["foreign"]["name"]
local_name = symbol_alias["local"]
import_directive.renaming[local_name] = original_name
# Assuming that two imports cannot collide in renaming
scope.renaming[local_name] = original_name

# This path should only be hit for the malformed AST of solc 0.5.12 where
# the foreign identifier cannot be found but is required to resolve the alias.
# see https://github.com/crytic/slither/issues/1319
elif symbol_alias["local"]:
raise SlitherException(
"Cannot resolve local alias for import directive due to malformed AST. Please upgrade to solc 0.6.0 or higher."
)
if "foreign" in symbol_alias:
original_name = symbol_alias["foreign"]["name"]
to_import.append(original_name)
if "local" in symbol_alias:
if isinstance(symbol_alias["foreign"], dict) and "name" in symbol_alias["foreign"]:
local_name = symbol_alias["local"]
import_directive.renaming[local_name] = original_name
# Assuming that two imports cannot collide in renaming
scope.renaming[local_name] = original_name

# This path should only be hit for the malformed AST of solc 0.5.12 where
# the foreign identifier cannot be found but is required to resolve the alias.
# see https://github.com/crytic/slither/issues/1319
elif symbol_alias["local"]:
raise SlitherException(
"Cannot resolve local alias for import directive due to malformed AST. Please upgrade to solc 0.6.0 or higher."
)

return to_import

class SlitherCompilationUnitSolc(CallerContextExpression):
# pylint: disable=no-self-use,too-many-instance-attributes
Expand Down Expand Up @@ -257,6 +260,7 @@ def parse_top_level_from_loaded_json(self, data_loaded: Dict, filename: str) ->
self._using_for_top_level_parser.append(usingFor_parser)

elif top_level_data[self.get_key()] == "ImportDirective":
to_import = []
if self.is_compact_ast:
import_directive = Import(
Path(
Expand All @@ -270,7 +274,7 @@ def parse_top_level_from_loaded_json(self, data_loaded: Dict, filename: str) ->
import_directive.alias = top_level_data["unitAlias"]
if "symbolAliases" in top_level_data:
symbol_aliases = top_level_data["symbolAliases"]
_handle_import_aliases(symbol_aliases, import_directive, scope)
to_import = _handle_import_aliases(symbol_aliases, import_directive, scope)
else:
import_directive = Import(
Path(
Expand All @@ -289,7 +293,7 @@ def parse_top_level_from_loaded_json(self, data_loaded: Dict, filename: str) ->
self._compilation_unit.import_directives.append(import_directive)

get_imported_scope = self.compilation_unit.get_scope(import_directive.filename)
scope.accessible_scopes.append(get_imported_scope)
scope.accessible_scopes.append(FileScopeToImport(get_imported_scope, to_import))

elif top_level_data[self.get_key()] == "StructDefinition":
st = StructureTopLevel(self.compilation_unit, scope)
Expand Down

0 comments on commit 256ca32

Please sign in to comment.