fix phi placement by calling SlitherCompilationUnit.add_function

pull/2099/head
alpharush 1 year ago
parent 66def310e7
commit e287b2f905
  1. 4
      slither/core/compilation_unit.py
  2. 6
      slither/vyper_parsing/declarations/contract.py
  3. 15
      tests/unit/slithir/vyper/test_ir_generation.py

@ -189,6 +189,10 @@ class SlitherCompilationUnit(Context):
return self.functions + list(self.modifiers) return self.functions + list(self.modifiers)
def propagate_function_calls(self) -> None: def propagate_function_calls(self) -> None:
"""This info is used to compute the rvalues of Phi operations in `fix_phi` and ultimately
is responsible for the `read` property of Phi operations which is vital to
propagating taints inter-procedurally
"""
for f in self.functions_and_modifiers: for f in self.functions_and_modifiers:
for node in f.nodes: for node in f.nodes:
for ir in node.irs_ssa: for ir in node.irs_ssa:

@ -1,4 +1,5 @@
import logging import logging
from pathlib import Path
from typing import List, TYPE_CHECKING from typing import List, TYPE_CHECKING
from slither.vyper_parsing.ast.types import ( from slither.vyper_parsing.ast.types import (
Module, Module,
@ -40,7 +41,9 @@ class ContractVyper:
self._contract: Contract = contract self._contract: Contract = contract
self._slither_parser: "VyperCompilationUnit" = slither_parser self._slither_parser: "VyperCompilationUnit" = slither_parser
self._data = module self._data = module
self._contract.name = module.name # Vyper models only have one contract (aside from interfaces) and the name is the file path
# We use the stem to make it a more user friendly name that is easy to query via canonical name
self._contract.name = Path(module.name).stem
self._contract.id = module.node_id self._contract.id = module.node_id
self._is_analyzed: bool = False self._is_analyzed: bool = False
@ -492,6 +495,7 @@ class ContractVyper:
func_parser = FunctionVyper(func, function, self) func_parser = FunctionVyper(func, function, self)
self._contract.add_function(func) self._contract.add_function(func)
self._contract.compilation_unit.add_function(func)
self._functions_parser.append(func_parser) self._functions_parser.append(func_parser)
self._functionsNotParsed = [] self._functionsNotParsed = []

@ -64,6 +64,7 @@ def bar():
assert contract == interface assert contract == interface
assert function.signature_str == "foo() returns(int128,uint256)" assert function.signature_str == "foo() returns(int128,uint256)"
def test_phi_entry_point_internal_call(slither_from_vyper_source): def test_phi_entry_point_internal_call(slither_from_vyper_source):
with slither_from_vyper_source( with slither_from_vyper_source(
""" """
@ -78,5 +79,15 @@ def a(x: uint256):
self.b(1) self.b(1)
""" """
) as sl: ) as sl:
b = sl.contracts[0].get_function_from_signature("b(uint256)") f = sl.contracts[0].get_function_from_signature("b(uint256)")
assert len(list(filter(lambda x: isinstance(x, Phi), b.all_slithir_operations()))) == 1 assert (
len(
[
ssanode
for node in f.nodes
for ssanode in node.irs_ssa
if isinstance(ssanode, Phi)
]
)
== 1
)

Loading…
Cancel
Save