From c919cdae037ca4e7d6091235d1bdf3ee5097b804 Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Thu, 22 Jun 2023 16:55:37 +0400 Subject: [PATCH 1/7] added reachability field for node which indicates whether the node is reachable from the ENTRY_POINT --- slither/core/cfg/node.py | 9 +++++++++ 1 file changed, 9 insertions(+) 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 ################################################################################### ################################################################################### From 7b9024f96b12d885248b83b8faeb0edf9d326056 Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Thu, 22 Jun 2023 16:56:25 +0400 Subject: [PATCH 2/7] the reachability is updated as the last step of cfg parsing --- slither/solc_parsing/declarations/function.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 35ca51aebe..1ecfd3bf62 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -1100,6 +1100,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): + 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" @@ -1120,6 +1127,8 @@ def _parse_cfg(self, cfg: Dict) -> None: self._remove_incorrect_edges() self._remove_alone_endif() + self._update_reachability(self._function.entry_point) + # endregion ################################################################################### ################################################################################### From 49a31173ee0e08fbdf740fd571d1344ed87e61d8 Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Thu, 22 Jun 2023 16:58:55 +0400 Subject: [PATCH 3/7] now we intersect only reachable fathers' dominators --- slither/core/dominators/utils.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/slither/core/dominators/utils.py b/slither/core/dominators/utils.py index 4dd55749d9..463eac4b7b 100644 --- a/slither/core/dominators/utils.py +++ b/slither/core/dominators/utils.py @@ -9,11 +9,17 @@ 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) - return ret + 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 def _compute_dominators(nodes: List["Node"]) -> None: changed = True @@ -84,6 +90,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 From d75d8d8d8e411515944989ea09c235386d66d30d Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Thu, 22 Jun 2023 17:03:48 +0400 Subject: [PATCH 4/7] changed by black --- slither/core/dominators/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/slither/core/dominators/utils.py b/slither/core/dominators/utils.py index 463eac4b7b..77ff22611f 100644 --- a/slither/core/dominators/utils.py +++ b/slither/core/dominators/utils.py @@ -21,6 +21,7 @@ def intersection_predecessor(node: "Node") -> Set["Node"]: ret = ret.intersection(pred.dominators) return ret + def _compute_dominators(nodes: List["Node"]) -> None: changed = True From 6e156718d3d9594b738d10565daf3cfb83277a4f Mon Sep 17 00:00:00 2001 From: "t.avagyan" Date: Mon, 26 Jun 2023 09:17:17 +0400 Subject: [PATCH 5/7] fixed dfs --- slither/solc_parsing/declarations/function.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 1ecfd3bf62..3df121e8ff 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -315,6 +315,8 @@ def analyze_content(self) -> None: self._remove_alone_endif() + self._update_reachability(self._function.entry_point) + # endregion ################################################################################### ################################################################################### @@ -1127,8 +1129,6 @@ def _parse_cfg(self, cfg: Dict) -> None: self._remove_incorrect_edges() self._remove_alone_endif() - self._update_reachability(self._function.entry_point) - # endregion ################################################################################### ################################################################################### From cee0c6bd73c004208a86ed1880edc3757bb0227d Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Mon, 26 Jun 2023 09:30:43 +0400 Subject: [PATCH 6/7] added nullcheck for functions not having entry point (non implemented functions) --- slither/solc_parsing/declarations/function.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 3df121e8ff..b3821388bf 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -315,7 +315,8 @@ def analyze_content(self) -> None: self._remove_alone_endif() - self._update_reachability(self._function.entry_point) + if self._function.entry_point: + self._update_reachability(self._function.entry_point) # endregion ################################################################################### From 6f27239d48551cdccccc2ee2e9d4da9470180fbf Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Mon, 11 Sep 2023 13:10:07 +0400 Subject: [PATCH 7/7] added type annotation --- slither/solc_parsing/declarations/function.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index b3821388bf..6097d2304d 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -1103,7 +1103,7 @@ 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): + def _update_reachability(self, node: Node) -> None: if node.is_reachable: return node.set_is_reachable(True)