Skip to content

Commit

Permalink
Merge branch 'dev' into dev-echidna
Browse files Browse the repository at this point in the history
  • Loading branch information
montyly committed Oct 13, 2023
2 parents b265089 + 2c76c94 commit 3faf1bf
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 0 deletions.
1 change: 1 addition & 0 deletions slither/core/declarations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
from .custom_error_contract import CustomErrorContract
from .custom_error_top_level import CustomErrorTopLevel
from .custom_error import CustomError
from .solidity_import_placeholder import SolidityImportPlaceHolder
67 changes: 67 additions & 0 deletions slither/visitors/slithir/expression_to_slithir.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Union, List, TYPE_CHECKING, Any

from slither.core import expressions
from slither.core.scope.scope import FileScope
from slither.core.declarations import (
Function,
SolidityVariable,
Expand All @@ -11,6 +12,8 @@
EnumContract,
EnumTopLevel,
Enum,
SolidityImportPlaceHolder,
Import,
Structure,
)
from slither.core.expressions import (
Expand Down Expand Up @@ -600,12 +603,76 @@ def _post_member_access(self, expression: MemberAccess) -> None:
set_val(expression, expr.enums_as_dict[str(expression)])
return

if isinstance(expr, (SolidityImportPlaceHolder, Import)):
scope = (
expr.import_directive.scope
if isinstance(expr, SolidityImportPlaceHolder)
else expr.scope
)
if self._check_elem_in_scope(expression.member_name, scope, expression):
return

val_ref = ReferenceVariable(self._node)
member = Member(expr, Constant(expression.member_name), val_ref)
member.set_expression(expression)
self._result.append(member)
set_val(expression, val_ref)

def _check_elem_in_scope(self, elem: str, scope: FileScope, expression: MemberAccess) -> bool:
if elem in scope.renaming:
self._check_elem_in_scope(scope.renaming[elem], scope, expression)
return True

if elem in scope.contracts:
set_val(expression, scope.contracts[elem])
return True

if elem in scope.structures:
set_val(expression, scope.structures[elem])
return True

if elem in scope.variables:
set_val(expression, scope.variables[elem])
return True

if elem in scope.enums:
set_val(expression, scope.enums[elem])
return True

if elem in scope.type_aliases:
set_val(expression, scope.type_aliases[elem])
return True

for import_directive in scope.imports:
if elem == import_directive.alias:
set_val(expression, import_directive)
return True

for custom_error in scope.custom_errors:
if custom_error.name == elem:
set_val(expression, custom_error)
return True

if str(expression.type).startswith("function "):
# This is needed to handle functions overloading
signature_to_seaarch = (
str(expression.type)
.replace("function ", elem)
.replace("pure ", "")
.replace("view ", "")
.replace("struct ", "")
.replace("enum ", "")
.replace(" memory", "")
.split(" returns", maxsplit=1)[0]
)

for function in scope.functions:
if signature_to_seaarch == function.full_name:
set_val(expression, function)
return True

return False

def _post_new_array(self, expression: NewArray) -> None:
val = TemporaryVariable(self._node)
operation = TmpNewArray(expression.array_type, val)
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/solc_parsing/test_ast_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]:
["0.6.9", "0.7.6", "0.8.16"],
),
Test("user_defined_operators-0.8.19.sol", ["0.8.19"]),
Test("aliasing/main.sol", ["0.8.19"]),
Test("type-aliases.sol", ["0.8.19"]),
Test("enum-max-min.sol", ["0.8.19"]),
]
Expand Down
24 changes: 24 additions & 0 deletions tests/e2e/solc_parsing/test_data/aliasing/l1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import "./l2.sol" as L2;
import {MyErr as MyImportError} from "./l3.sol";

type fd is uint;
error MyError();
uint constant qwe = 34;

struct SS {
uint g;
}

enum MyEnum {
A,
B
}

function tpf(MyEnum p) returns(uint) {return 4;}
function tpf(fd p) pure returns(uint) {return 4;}
function tpf(uint e, SS memory g) view returns(uint) {return 4;}

library MyC {
function callme() public {}

}
1 change: 1 addition & 0 deletions tests/e2e/solc_parsing/test_data/aliasing/l2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
function l() {}
1 change: 1 addition & 0 deletions tests/e2e/solc_parsing/test_data/aliasing/l3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
error MyErr();
20 changes: 20 additions & 0 deletions tests/e2e/solc_parsing/test_data/aliasing/main.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import "./l1.sol" as R;

contract Tp {

function re(R.SS calldata param1, R.MyEnum param2) public {
R.MyEnum a = R.MyEnum.A;
R.SS memory b = R.SS(R.qwe);
R.MyC.callme();
R.tpf(2, param1);
R.tpf(param2);
R.tpf(R.fd.wrap(4));
R.L2.l();
revert R.MyImportError();
}

function re2() public {
revert R.MyError();
}

}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"MyC": {
"callme()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
},
"Tp": {
"re(SS,MyEnum)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n}\n",
"re2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
}
}

0 comments on commit 3faf1bf

Please sign in to comment.