Skip to content

Commit

Permalink
Merge pull request #1604 from bart1e/missing_references_fix
Browse files Browse the repository at this point in the history
Missing references fix
  • Loading branch information
montyly authored Feb 14, 2023
2 parents 6a3435f + 5b09336 commit 04a6b0f
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 2 deletions.
4 changes: 3 additions & 1 deletion slither/solc_parsing/expressions/expression_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from slither.core.solidity_types import (
ArrayType,
ElementaryType,
UserDefinedType,
)
from slither.solc_parsing.declarations.caller_context import CallerContextExpression
from slither.solc_parsing.exceptions import ParsingError, VariableNotFound
Expand Down Expand Up @@ -112,7 +113,6 @@ def parse_call(expression: Dict, caller_context): # pylint: disable=too-many-st

if type_conversion:
type_call = parse_type(UnknownType(type_return), caller_context)

if caller_context.is_compact_ast:
assert len(expression["arguments"]) == 1
expression_to_parse = expression["arguments"][0]
Expand All @@ -133,6 +133,8 @@ def parse_call(expression: Dict, caller_context): # pylint: disable=too-many-st
expression = parse_expression(expression_to_parse, caller_context)
t = TypeConversion(expression, type_call)
t.set_offset(src, caller_context.compilation_unit)
if isinstance(type_call, UserDefinedType):
type_call.type.references.append(t.source_mapping)
return t

call_gas = None
Expand Down
7 changes: 6 additions & 1 deletion slither/solc_parsing/solidity_types/type_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel
from slither.core.declarations.function_contract import FunctionContract
from slither.core.expressions.literal import Literal
from slither.core.solidity_types import TypeAlias
from slither.core.solidity_types import TypeAlias, TypeAliasTopLevel, TypeAliasContract
from slither.core.solidity_types.array_type import ArrayType
from slither.core.solidity_types.elementary_type import (
ElementaryType,
Expand Down Expand Up @@ -199,6 +199,9 @@ def _add_type_references(type_found: Type, src: str, sl: "SlitherCompilationUnit

if isinstance(type_found, UserDefinedType):
type_found.type.add_reference_from_raw_source(src, sl)
elif isinstance(type_found, (TypeAliasTopLevel, TypeAliasContract)):
type_found.type.add_reference_from_raw_source(src, sl)
type_found.add_reference_from_raw_source(src, sl)


# TODO: since the add of FileScope, we can probably refactor this function and makes it a lot simpler
Expand Down Expand Up @@ -362,6 +365,7 @@ def parse_type(
if name in renaming:
name = renaming[name]
if name in user_defined_types:
_add_type_references(user_defined_types[name], t["src"], sl)
return user_defined_types[name]
type_found = _find_from_type_name(
name,
Expand All @@ -382,6 +386,7 @@ def parse_type(
if name in renaming:
name = renaming[name]
if name in user_defined_types:
_add_type_references(user_defined_types[name], t["src"], sl)
return user_defined_types[name]
type_found = _find_from_type_name(
name,
Expand Down
19 changes: 19 additions & 0 deletions tests/src_mapping/ReferencesUserDefinedAliases.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pragma solidity 0.8.16;

type aliasTopLevel is uint;

contract C
{
type aliasContractLevel is uint;
}

contract Test
{
aliasTopLevel a;
C.aliasContractLevel b;
}

function f(aliasTopLevel, C.aliasContractLevel)
{

}
19 changes: 19 additions & 0 deletions tests/src_mapping/ReferencesUserDefinedTypesCasting.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pragma solidity 0.8.16;

interface A
{
function a() external;
}

contract C
{
function g(address _address) private
{
A(_address).a();
}
}

function f(address _address)
{
A(_address).a();
}
50 changes: 50 additions & 0 deletions tests/test_source_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,53 @@ def test_source_mapping():
(x.start, x.end)
for x in slither.offset_to_implementations("tests/src_mapping/inheritance.sol", 93)
} == {(17, 53), (193, 230), (129, 166)}


def _sort_references_lines(refs: list) -> list:
return sorted([ref.lines[0] for ref in refs])


def _test_references_user_defined_aliases():
"""
Tests if references are filled correctly for user defined aliases (declared using "type [...] is [...]" statement).
"""
solc_select.switch_global_version("0.8.16", always_install=True)
slither = Slither("tests/src_mapping/ReferencesUserDefinedAliases.sol")

alias_top_level = slither.compilation_units[0].user_defined_value_types["aliasTopLevel"]
assert len(alias_top_level.references) == 2
lines = _sort_references_lines(alias_top_level.references)
assert lines == [12, 16]

alias_contract_level = (
slither.compilation_units[0]
.contracts[0]
.file_scope.user_defined_types["C.aliasContractLevel"]
)
assert len(alias_contract_level.references) == 2
lines = _sort_references_lines(alias_contract_level.references)
assert lines == [13, 16]


def _test_references_user_defined_types_when_casting():
"""
Tests if references are filled correctly for user defined types in case of casting.
"""
solc_select.switch_global_version("0.8.16", always_install=True)
slither = Slither("tests/src_mapping/ReferencesUserDefinedTypesCasting.sol")

contracts = slither.compilation_units[0].contracts
a = contracts[0] if contracts[0].is_interface else contracts[1]
assert len(a.references) == 2
lines = _sort_references_lines(a.references)
assert lines == [12, 18]


def test_references():
"""
Tests if references list is filled correctly in the following cases:
- user defined aliases (declared using "type [...] is [...]" statement)
- user defined types in case of casting (TypeConversion expressions)
"""
_test_references_user_defined_aliases()
_test_references_user_defined_types_when_casting()

0 comments on commit 04a6b0f

Please sign in to comment.