Merge pull request #1917 from crytic/dev-yul-functions-call

Fix yul function calls
pull/1961/head
Feist Josselin 1 year ago committed by GitHub
commit aafdf345b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 33
      slither/solc_parsing/yul/parse_yul.py
  2. 4
      tests/e2e/solc_parsing/test_ast_parsing.py
  3. 12
      tests/e2e/solc_parsing/test_data/assembly-functions.sol
  4. BIN
      tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.6.9-compact.zip
  5. BIN
      tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.6.9-legacy.zip
  6. BIN
      tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.7.6-compact.zip
  7. BIN
      tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.7.6-legacy.zip
  8. BIN
      tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.8.16-compact.zip
  9. 12
      tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json
  10. 5
      tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-legacy.json
  11. 12
      tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json
  12. 5
      tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-legacy.json
  13. 12
      tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json

@ -181,7 +181,7 @@ class YulScope(metaclass=abc.ABCMeta):
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,
@ -252,6 +252,10 @@ class YulFunction(YulScope):
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)
@ -271,6 +275,9 @@ class YulFunction(YulScope):
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:
@ -325,7 +332,10 @@ class YulBlock(YulScope):
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:
@ -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
@ -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"]
@ -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

@ -453,6 +453,10 @@ ALL_TESTS = [
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:

@ -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()
}
}
}

@ -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,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"
}
}

@ -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,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"
}
}

@ -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"
}
}
Loading…
Cancel
Save