Use cache system for function.all_* properties

pull/162/head
Josselin 6 years ago
parent 1cdc34ec77
commit 00c38a0945
  1. 154
      slither/core/declarations/function.py

@ -60,6 +60,21 @@ class Function(ChildContract, SourceMapping):
self._payable = False
self._contains_assembly = False
self._expressions = None
self._slithir_operations = None
self._all_expressions = None
self._all_slithir_operations = None
self._all_internals_calls = None
self._all_high_level_calls = None
self._all_low_level_calls = None
self._all_state_variables_read = None
self._all_solidity_variables_read = None
self._all_state_variables_written = None
self._all_conditional_state_variables_read = None
self._all_conditional_solidity_variables_read = None
self._all_solidity_variables_used_as_args = None
@property
def contains_assembly(self):
return self._contains_assembly
@ -281,7 +296,7 @@ class Function(ChildContract, SourceMapping):
def variables_written_as_expression(self):
return self._expression_vars_written
@property
@property
def slithir_variables(self):
'''
Temporary and Reference Variables (not SSA form)
@ -340,9 +355,22 @@ class Function(ChildContract, SourceMapping):
"""
list(Expression): List of the expressions
"""
expressions = [n.expression for n in self.nodes]
expressions = [e for e in expressions if e]
return expressions
if self._expressions is None:
expressions = [n.expression for n in self.nodes]
expressions = [e for e in expressions if e]
self._expressions = expressions
return self._expressions
@property
def slithir_operations(self):
"""
list(Operation): List of the slithir operations
"""
if self._slithir_operations is None:
operations = [n.irs for n in self.nodes]
operations = [item for sublist in operations for item in sublist if item]
self._slithir_operations = operations
return self._slithir_operations
@property
def signature(self):
@ -518,27 +546,66 @@ class Function(ChildContract, SourceMapping):
def all_state_variables_read(self):
""" recursive version of variables_read
"""
return self._explore_functions(lambda x: x.state_variables_read)
if self._all_state_variables_read is None:
self._all_state_variables_read = self._explore_functions(
lambda x: x.state_variables_read)
return self._all_state_variables_read
def all_solidity_variables_read(self):
""" recursive version of solidity_read
"""
return self._explore_functions(lambda x: x.solidity_variables_read)
if self._all_solidity_variables_read is None:
self._all_solidity_variables_read = self._explore_functions(
lambda x: x.solidity_variables_read)
return self._all_solidity_variables_read
def all_expressions(self):
""" recursive version of variables_read
"""
return self._explore_functions(lambda x: x.expressions)
if self._all_expressions is None:
self._all_expressions = self._explore_functions(lambda x: x.expressions)
return self._all_expressions
def all_slithir_operations(self):
"""
"""
if self._all_slithir_operations is None:
self._all_slithir_operations = self._explore_functions(lambda x: x.slithir_operations)
return self._all_slithir_operations
def all_state_variables_written(self):
""" recursive version of variables_written
"""
return self._explore_functions(lambda x: x.state_variables_written)
if self._all_state_variables_written is None:
self._all_state_variables_written = self._explore_functions(
lambda x: x.state_variables_written)
return self._all_state_variables_written
def all_internal_calls(self):
""" recursive version of internal_calls
"""
return self._explore_functions(lambda x: x.internal_calls)
if self._all_internals_calls is None:
self._all_internals_calls = self._explore_functions(lambda x: x.internal_calls)
return self._all_internals_calls
def all_low_level_calls(self):
""" recursive version of low_level calls
"""
if self._all_low_level_calls is None:
self._all_low_level_calls = self._explore_functions(lambda x: x.low_level_calls)
return self._all_low_level_calls
def all_high_level_calls(self):
""" recursive version of high_level calls
"""
if self._all_high_level_calls is None:
self._all_high_level_calls = self._explore_functions(lambda x: x.high_level_calls)
return self._all_high_level_calls
@staticmethod
def _explore_func_cond_read(func, include_loop):
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]
def all_conditional_state_variables_read(self, include_loop=True):
"""
@ -547,10 +614,25 @@ class Function(ChildContract, SourceMapping):
Over approximate and also return index access
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(include_loop)]
return [item for sublist in ret for item in sublist]
return self._explore_functions(lambda x: _explore_func(x))
if self._all_conditional_state_variables_read is None:
self._all_conditional_state_variables_read = self._explore_functions(
lambda x: self._explore_func_cond_read(x,
include_loop))
return self._all_conditional_state_variables_read
@staticmethod
def _solidity_variable_in_binary(node):
from slither.slithir.operations.binary import Binary
ret = []
for ir in node.irs:
if isinstance(ir, Binary):
ret += ir.read
return [var for var in ret if isinstance(var, SolidityVariable)]
@staticmethod
def _explore_func_conditional(func, f, include_loop):
ret = [f(n) for n in func.nodes if n.is_conditional(include_loop)]
return [item for sublist in ret for item in sublist]
def all_conditional_solidity_variables_read(self, include_loop=True):
"""
@ -560,17 +642,26 @@ class Function(ChildContract, SourceMapping):
Assumption: the solidity vars are used directly in the conditional node
It won't work if the variable is assigned to a temp variable
"""
from slither.slithir.operations.binary import Binary
def _solidity_variable_in_node(node):
ret = []
for ir in node.irs:
if isinstance(ir, Binary):
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(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))
if self._all_conditional_solidity_variables_read is None:
self._all_conditional_solidity_variables_read = self._explore_functions(
lambda x: self._explore_func_conditional(x,
self._solidity_variable_in_binary,
include_loop))
return self._all_conditional_solidity_variables_read
@staticmethod
def _solidity_variable_in_internal_calls(node):
from slither.slithir.operations.internal_call import InternalCall
ret = []
for ir in node.irs:
if isinstance(ir, InternalCall):
ret += ir.read
return [var for var in ret if isinstance(var, SolidityVariable)]
@staticmethod
def _explore_func_nodes(func, f):
ret = [f(n) for n in func.nodes]
return [item for sublist in ret for item in sublist]
def all_solidity_variables_used_as_args(self):
"""
@ -579,17 +670,10 @@ class Function(ChildContract, SourceMapping):
Use of the IR to filter index access
Used to catch check(msg.sender)
"""
from slither.slithir.operations.internal_call import InternalCall
def _solidity_variable_in_node(node):
ret = []
for ir in node.irs:
if isinstance(ir, InternalCall):
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]
return [item for sublist in ret for item in sublist]
return self._explore_functions(lambda x: _explore_func(x, _solidity_variable_in_node))
if self._all_solidity_variables_used_as_args is None:
self._all_solidity_variables_used_as_args = self._explore_functions(
lambda x: self._explore_func_nodes(x, self._solidity_variable_in_internal_calls))
return self._all_solidity_variables_used_as_args
def is_reading(self, variable):
"""

Loading…
Cancel
Save