diff --git a/slither/core/cfg/node.py b/slither/core/cfg/node.py index 2a48bd2358..475e2f1389 100644 --- a/slither/core/cfg/node.py +++ b/slither/core/cfg/node.py @@ -193,6 +193,8 @@ def __init__( self.file_scope: "FileScope" = file_scope self._function: Optional["Function"] = None + self._is_reachable: bool = False + ################################################################################### ################################################################################### # region General's properties @@ -234,6 +236,13 @@ def set_function(self, function: "Function") -> None: def function(self) -> "Function": return self._function + @property + def is_reachable(self) -> bool: + return self._is_reachable + + def set_is_reachable(self, new_is_reachable: bool) -> None: + self._is_reachable = new_is_reachable + # endregion ################################################################################### ################################################################################### diff --git a/slither/core/dominators/utils.py b/slither/core/dominators/utils.py index 4dd55749d9..77ff22611f 100644 --- a/slither/core/dominators/utils.py +++ b/slither/core/dominators/utils.py @@ -9,9 +9,16 @@ def intersection_predecessor(node: "Node") -> Set["Node"]: if not node.fathers: return set() - ret = node.fathers[0].dominators - for pred in node.fathers[1:]: - ret = ret.intersection(pred.dominators) + if not any(father.is_reachable for father in node.fathers): + return set() + + ret = set() + for pred in node.fathers: + ret = ret.union(pred.dominators) + + for pred in node.fathers: + if pred.is_reachable: + ret = ret.intersection(pred.dominators) return ret @@ -84,6 +91,8 @@ def compute_dominance_frontier(nodes: List["Node"]) -> None: for node in nodes: if len(node.fathers) >= 2: for father in node.fathers: + if not father.is_reachable: + continue runner = father # Corner case: if there is a if without else # we need to add update the conditional node diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 35ca51aebe..6097d2304d 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -315,6 +315,9 @@ def analyze_content(self) -> None: self._remove_alone_endif() + if self._function.entry_point: + self._update_reachability(self._function.entry_point) + # endregion ################################################################################### ################################################################################### @@ -1100,6 +1103,13 @@ def _parse_unchecked_block(self, block: Dict, node: NodeSolc, scope): node = self._parse_statement(statement, node, new_scope) return node + def _update_reachability(self, node: Node) -> None: + if node.is_reachable: + return + node.set_is_reachable(True) + for son in node.sons: + self._update_reachability(son) + def _parse_cfg(self, cfg: Dict) -> None: assert cfg[self.get_key()] == "Block"