From 15c166cfbbff88d804370991daa172d0b4569dc0 Mon Sep 17 00:00:00 2001 From: Josselin Date: Wed, 9 Jan 2019 09:19:16 +0000 Subject: [PATCH] Allow to include/exclude loops for node.is_condition --- slither/core/cfg/node.py | 10 ++++++---- slither/core/declarations/function.py | 10 +++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/slither/core/cfg/node.py b/slither/core/cfg/node.py index 161b1e5dc..05ec3de81 100644 --- a/slither/core/cfg/node.py +++ b/slither/core/cfg/node.py @@ -386,22 +386,24 @@ class Node(SourceMapping, ChildFunction): """ return any(c.name in ['require(bool)', 'require(bool,string)', 'assert(bool)'] for c in self.internal_calls) - def contains_if(self): + def contains_if(self, include_loop=True): """ Check if the node is a IF node Returns: bool: True if the node is a conditional node (IF or IFLOOP) """ - return self.type in [NodeType.IF, NodeType.IFLOOP] + if include_loop: + return self.type in [NodeType.IF, NodeType.IFLOOP] + return self.type == NodeType.IF - def is_conditional(self): + def is_conditional(self, include_loop=True): """ Check if the node is a conditional node A conditional node is either a IF or a require/assert Returns: bool: True if the node is a conditional node """ - return self.contains_if() or self.contains_require_or_assert() + return self.contains_if(include_loop) or self.contains_require_or_assert() def add_father(self, father): """ Add a father node diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index aaae9d20f..d32f1563c 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -528,7 +528,7 @@ class Function(ChildContract, SourceMapping): """ return self._explore_functions(lambda x: x.internal_calls) - def all_conditional_state_variables_read(self): + def all_conditional_state_variables_read(self, include_loop=True): """ Return the state variable used in a condition @@ -536,11 +536,11 @@ class Function(ChildContract, SourceMapping): It won't work if the variable is assigned to a temp variable """ def _explore_func(func): - ret = [n.state_variables_read for n in func.nodes if n.is_conditional()] + ret = [n.state_variables_read for n in func.nodes if n.is_conditional(include_loop)] return [item for sublist in ret for item in sublist] return self._explore_functions(lambda x: _explore_func(x)) - def all_conditional_solidity_variables_read(self): + def all_conditional_solidity_variables_read(self, include_loop=True): """ Return the Soldiity variables directly used in a condtion @@ -556,7 +556,7 @@ class Function(ChildContract, SourceMapping): ret += ir.read return [var for var in ret if isinstance(var, SolidityVariable)] def _explore_func(func, f): - ret = [f(n) for n in func.nodes if n.is_conditional()] + ret = [f(n) for n in func.nodes if n.is_conditional(include_loop)] return [item for sublist in ret for item in sublist] return self._explore_functions(lambda x: _explore_func(x, _solidity_variable_in_node)) @@ -721,7 +721,7 @@ class Function(ChildContract, SourceMapping): if self.is_constructor: return True - conditional_vars = self.all_conditional_solidity_variables_read() + conditional_vars = self.all_conditional_solidity_variables_read(include_loop=False) args_vars = self.all_solidity_variables_used_as_args() return SolidityVariableComposed('msg.sender') in conditional_vars + args_vars