Skip to content

Commit

Permalink
Merge pull request #1917 from crytic/dev-yul-functions-call
Browse files Browse the repository at this point in the history
Fix yul function calls
  • Loading branch information
montyly authored Jun 9, 2023
2 parents fc28eee + 413a50a commit aafdf34
Show file tree
Hide file tree
Showing 13 changed files with 92 additions and 3 deletions.
33 changes: 30 additions & 3 deletions slither/solc_parsing/yul/parse_yul.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def get_yul_local_variable_from_name(self, variable_name: str) -> Optional["YulL
def add_yul_local_function(self, func: "YulFunction") -> None:
self._yul_local_functions.append(func)

def get_yul_local_function_from_name(self, func_name: str) -> Optional["YulLocalVariable"]:
def get_yul_local_function_from_name(self, func_name: str) -> Optional["YulFunction"]:
return next(
(v for v in self._yul_local_functions if v.underlying.name == func_name),
None,
Expand Down Expand Up @@ -252,6 +252,10 @@ def underlying(self) -> Function:
def function(self) -> Function:
return self._function

@property
def root(self) -> YulScope:
return self._root

def convert_body(self) -> None:
node = self.new_node(NodeType.ENTRYPOINT, self._ast["src"])
link_underlying_nodes(self._entrypoint, node)
Expand All @@ -271,6 +275,9 @@ def convert_body(self) -> None:
def parse_body(self) -> None:
for node in self._nodes:
node.analyze_expressions()
for f in self._yul_local_functions:
if f != self:
f.parse_body()

def new_node(self, node_type: NodeType, src: str) -> YulNode:
if self._function:
Expand Down Expand Up @@ -325,7 +332,10 @@ def new_node(self, node_type: NodeType, src: Union[str, Dict]) -> YulNode:
return yul_node

def convert(self, ast: Dict) -> YulNode:
return convert_yul(self, self._entrypoint, ast, self.node_scope)
yul_node = convert_yul(self, self._entrypoint, ast, self.node_scope)
for f in self._yul_local_functions:
f.parse_body()
return yul_node

def analyze_expressions(self) -> None:
for node in self._nodes:
Expand Down Expand Up @@ -390,7 +400,6 @@ def convert_yul_function_definition(
root.add_yul_local_function(yul_function)

yul_function.convert_body()
yul_function.parse_body()

return parent

Expand Down Expand Up @@ -778,6 +787,7 @@ def _parse_yul_magic_suffixes(name: str, root: YulScope) -> Optional[Expression]
return None


# pylint: disable=too-many-branches
def parse_yul_identifier(root: YulScope, _node: YulNode, ast: Dict) -> Optional[Expression]:
name = ast["name"]

Expand Down Expand Up @@ -809,6 +819,23 @@ def parse_yul_identifier(root: YulScope, _node: YulNode, ast: Dict) -> Optional[
if func:
return Identifier(func.underlying)

# check yul-block scoped function
if isinstance(root, YulFunction):
yul_block = root.root

# Iterate until we searched in all the scopes until the YulBlock scope
while not isinstance(yul_block, YulBlock):
func = yul_block.get_yul_local_function_from_name(name)
if func:
return Identifier(func.underlying)

if isinstance(yul_block, YulFunction):
yul_block = yul_block.root

func = yul_block.get_yul_local_function_from_name(name)
if func:
return Identifier(func.underlying)

magic_suffix = _parse_yul_magic_suffixes(name, root)
if magic_suffix:
return magic_suffix
Expand Down
4 changes: 4 additions & 0 deletions tests/e2e/solc_parsing/test_ast_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,10 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]:
Test("complex_imports/import_aliases_issue_1319/test.sol", ["0.5.12"]),
Test("yul-state-constant-access.sol", ["0.8.16"]),
Test("negate-unary-element.sol", ["0.8.16"]),
Test(
"assembly-functions.sol",
["0.6.9", "0.7.6", "0.8.16"],
),
]
# create the output folder if needed
try:
Expand Down
12 changes: 12 additions & 0 deletions tests/e2e/solc_parsing/test_data/assembly-functions.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
contract A {
function foo() public {
assembly {
function f() { function z() { function x() { g() } x() } z() }
function w() { function a() {} function b() { a() } b() }
function g() {
f()
}
g()
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"A": {
"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: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.w()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.w.a()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n}\n",
"foo.asm_0.w.b()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.g()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +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"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"A": {
"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: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.w()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.w.a()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n}\n",
"foo.asm_0.w.b()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.g()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +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"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"A": {
"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: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.w()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.w.a()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n}\n",
"foo.asm_0.w.b()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"foo.asm_0.g()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n"
}
}

0 comments on commit aafdf34

Please sign in to comment.