Skip to content

Commit

Permalink
Merge pull request #2370 from crytic/fix/support-alias-NewContract
Browse files Browse the repository at this point in the history
fix: support aliases for NewContract operation
  • Loading branch information
0xalpharush authored Mar 29, 2024
2 parents 2ad318c + 294850f commit ef1fd7e
Show file tree
Hide file tree
Showing 11 changed files with 45 additions and 25 deletions.
7 changes: 3 additions & 4 deletions slither/slithir/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -871,9 +871,7 @@ def propagate_types(ir: Operation, node: "Node"): # pylint: disable=too-many-lo
elif isinstance(ir, NewArray):
ir.lvalue.set_type(ir.array_type)
elif isinstance(ir, NewContract):
contract = node.file_scope.get_contract_from_name(ir.contract_name)
assert contract
ir.lvalue.set_type(UserDefinedType(contract))
ir.lvalue.set_type(ir.contract_name)
elif isinstance(ir, NewElementaryType):
ir.lvalue.set_type(ir.type)
elif isinstance(ir, NewStructure):
Expand Down Expand Up @@ -1164,7 +1162,7 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]) -> Union[Call,
return n

if isinstance(ins.ori, TmpNewContract):
op = NewContract(Constant(ins.ori.contract_name), ins.lvalue)
op = NewContract(ins.ori.contract_name, ins.lvalue)
op.set_expression(ins.expression)
op.call_id = ins.call_id
if ins.call_value:
Expand Down Expand Up @@ -1719,6 +1717,7 @@ def convert_type_of_high_and_internal_level_call(
Returns:
Potential new IR
"""

func = None
if isinstance(ir, InternalCall):
candidates: List[Function]
Expand Down
14 changes: 7 additions & 7 deletions slither/slithir/operations/new_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from slither.core.declarations import Function
from slither.core.declarations.contract import Contract
from slither.core.variables import Variable
from slither.core.solidity_types import UserDefinedType
from slither.slithir.operations import Call, OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue
from slither.slithir.variables.constant import Constant
Expand All @@ -13,7 +14,7 @@
class NewContract(Call, OperationWithLValue): # pylint: disable=too-many-instance-attributes
def __init__(
self,
contract_name: Constant,
contract_name: UserDefinedType,
lvalue: Union[TemporaryVariableSSA, TemporaryVariable],
names: Optional[List[str]] = None,
) -> None:
Expand All @@ -23,7 +24,9 @@ def __init__(
For calls of the form f({argName1 : arg1, ...}), the names of parameters listed in call order.
Otherwise, None.
"""
assert isinstance(contract_name, Constant)
assert isinstance(
contract_name.type, Contract
), f"contract_name is {contract_name} of type {type(contract_name)}"
assert is_valid_lvalue(lvalue)
super().__init__(names=names)
self._contract_name = contract_name
Expand Down Expand Up @@ -58,7 +61,7 @@ def call_salt(self, s):
self._call_salt = s

@property
def contract_name(self) -> Constant:
def contract_name(self) -> UserDefinedType:
return self._contract_name

@property
Expand All @@ -69,10 +72,7 @@ def read(self) -> List[Any]:

@property
def contract_created(self) -> Contract:
contract_name = self.contract_name
contract_instance = self.node.file_scope.get_contract_from_name(contract_name)
assert contract_instance
return contract_instance
return self.contract_name.type

###################################################################################
###################################################################################
Expand Down
17 changes: 3 additions & 14 deletions slither/solc_parsing/expressions/expression_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,20 +614,9 @@ def parse_expression(expression: Dict, caller_context: CallerContextExpression)

assert type_name[caller_context.get_key()] == "UserDefinedTypeName"

if is_compact_ast:

# Changed introduced in Solidity 0.8
# see https://github.com/crytic/slither/issues/794

# TODO explore more the changes introduced in 0.8 and the usage of pathNode/IdentifierPath
if "name" not in type_name:
assert "pathNode" in type_name and "name" in type_name["pathNode"]
contract_name = type_name["pathNode"]["name"]
else:
contract_name = type_name["name"]
else:
contract_name = type_name["attributes"]["name"]
new = NewContract(contract_name)
contract_type = parse_type(type_name, caller_context)
assert isinstance(contract_type, UserDefinedType)
new = NewContract(contract_type)
new.set_offset(src, caller_context.compilation_unit)
return new

Expand Down
2 changes: 2 additions & 0 deletions tests/e2e/solc_parsing/test_ast_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,8 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]:
),
Test("user_defined_operators-0.8.19.sol", ["0.8.19"]),
Test("aliasing/main.sol", ["0.8.19"]),
Test("aliasing/alias-unit-NewContract.sol", ["0.8.19"]),
Test("aliasing/alias-symbol-NewContract.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"]),
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/solc_parsing/test_data/aliasing/MyContract.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
contract MyContract {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {MyContract as MyAliasedContract} from "./MyContract.sol";

contract Test {
MyAliasedContract c;
constructor() {
c = new MyAliasedContract();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

import "./MyContract.sol" as MyAliasedContract;

contract Test {
MyAliasedContract.MyContract c;
constructor() {
c = new MyAliasedContract.MyContract();
}
}
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"MyContract": {},
"Test": {
"constructor()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"MyContract": {},
"Test": {
"constructor()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
}
}

0 comments on commit ef1fd7e

Please sign in to comment.