diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 172449bc7..26e90faa5 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -1149,16 +1149,38 @@ class FunctionSolc(CallerContextExpression): return None - def _find_if_loop(self, node: Node, visited: List[Node]) -> Optional[Node]: + def _find_if_loop(self, node: Node, visited: List[Node], skip_if_loop: int) -> Optional[Node]: if node in visited: return None + # If skip_if_loop is not 0 it means we are in a nested situation + # and we have to skip the closer n loop headers. + # If in the fathers there is an EXPRESSION node it's a for loop + # and it's the index increment expression if node.type == NodeType.IFLOOP: - return node + if skip_if_loop == 0: + for father in node.fathers: + if father.type == NodeType.EXPRESSION: + return father + return node + + # skip_if_loop works as explained above. + # This handle when a for loop doesn't have a condition + # e.g. for (;;) {} + # and decrement skip_if_loop since we are out of the nested loop + if node.type == NodeType.STARTLOOP: + if skip_if_loop == 0: + return node + skip_if_loop -= 1 + + # If we find an ENDLOOP means we are in a nested loop + # we increment skip_if_loop counter + if node.type == NodeType.ENDLOOP: + skip_if_loop += 1 visited = visited + [node] for father in node.fathers: - ret = self._find_if_loop(father, visited) + ret = self._find_if_loop(father, visited, skip_if_loop) if ret: return ret @@ -1181,7 +1203,7 @@ class FunctionSolc(CallerContextExpression): end_node.add_father(node) def _fix_continue_node(self, node: Node) -> None: - if_loop_node = self._find_if_loop(node, []) + if_loop_node = self._find_if_loop(node, [], 0) if not if_loop_node: raise ParsingError(f"Continue in no-loop context {node.node_id}")