Merge branch 'dev' into dev-database

pull/172/head
Josselin 6 years ago
commit 31eba6c97c
  1. 5
      slither/__main__.py
  2. 17
      slither/analyses/data_dependency/data_dependency.py
  3. 19
      slither/core/cfg/node.py
  4. 2
      slither/detectors/reentrancy/reentrancy.py
  5. 3
      slither/printers/call/call_graph.py
  6. 2
      slither/printers/inheritance/inheritance_graph.py
  7. 263
      slither/slithir/utils/ssa.py
  8. 3
      slither/slithir/variables/__init__.py
  9. 18
      slither/slithir/variables/reference_ssa.py
  10. 20
      slither/slithir/variables/temporary_ssa.py
  11. 14
      slither/slithir/variables/tuple.py
  12. 20
      slither/slithir/variables/tuple_ssa.py
  13. 5
      slither/solc_parsing/solidity_types/type_parsing.py
  14. 4
      slither/visitors/slithir/expression_to_slithir.py

@ -78,7 +78,10 @@ def process_truffle(dirname, args, detector_classes, printer_classes):
package = json.load(f) package = json.load(f)
if 'devDependencies' in package: if 'devDependencies' in package:
if 'truffle' in package['devDependencies']: if 'truffle' in package['devDependencies']:
truffle_version = 'truffle@{}'.format(package['devDependencies']['truffle']) version = package['devDependencies']['truffle']
if version.startswith('^'):
version = version[1:]
truffle_version = 'truffle@{}'.format(version)
cmd = ['npx', truffle_version,'compile'] cmd = ['npx', truffle_version,'compile']
logger.info("'{}' running (use --truffle-version truffle@x.x.x to use specific version)".format(' '.join(cmd))) logger.info("'{}' running (use --truffle-version truffle@x.x.x to use specific version)".format(' '.join(cmd)))
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

@ -1,13 +1,14 @@
""" """
Compute the data depenency between all the SSA variables Compute the data depenency between all the SSA variables
""" """
from slither.core.declarations import Contract, Function from slither.core.declarations import (Contract, Enum, Function,
from slither.core.declarations.solidity_variables import \ SolidityFunction, SolidityVariable,
SolidityVariableComposed SolidityVariableComposed, Structure)
from slither.slithir.operations import Index, OperationWithLValue from slither.slithir.operations import Index, OperationWithLValue
from slither.slithir.variables import (Constant, LocalIRVariable, from slither.slithir.variables import (Constant, LocalIRVariable,
ReferenceVariable, StateIRVariable, ReferenceVariable, ReferenceVariableSSA,
TemporaryVariable) StateIRVariable, TemporaryVariable,
TemporaryVariableSSA, TupleVariableSSA)
################################################################################### ###################################################################################
################################################################################### ###################################################################################
@ -243,7 +244,6 @@ def compute_dependency_function(function):
function.context[KEY_SSA_UNPROTECTED] = dict() function.context[KEY_SSA_UNPROTECTED] = dict()
is_protected = function.is_protected() is_protected = function.is_protected()
for node in function.nodes: for node in function.nodes:
for ir in node.irs_ssa: for ir in node.irs_ssa:
if isinstance(ir, OperationWithLValue) and ir.lvalue: if isinstance(ir, OperationWithLValue) and ir.lvalue:
@ -259,10 +259,9 @@ def compute_dependency_function(function):
function.context[KEY_NON_SSA_UNPROTECTED] = convert_to_non_ssa(function.context[KEY_SSA_UNPROTECTED]) function.context[KEY_NON_SSA_UNPROTECTED] = convert_to_non_ssa(function.context[KEY_SSA_UNPROTECTED])
def convert_variable_to_non_ssa(v): def convert_variable_to_non_ssa(v):
if isinstance(v, (LocalIRVariable, StateIRVariable)): if isinstance(v, (LocalIRVariable, StateIRVariable, TemporaryVariableSSA, ReferenceVariableSSA, TupleVariableSSA)):
return v.non_ssa_version return v.non_ssa_version
if isinstance(v, (TemporaryVariable, ReferenceVariable)): assert isinstance(v, (Constant, SolidityVariable, Contract, Enum, SolidityFunction, Structure, Function))
return next((variable for variable in v.function.slithir_variables if variable.name == v.name))
return v return v
def convert_to_non_ssa(data_depencies): def convert_to_non_ssa(data_depencies):

@ -10,12 +10,13 @@ from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.variables.local_variable import LocalVariable from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.core.variables.variable import Variable from slither.core.variables.variable import Variable
from slither.core.solidity_types import ElementaryType
from slither.slithir.convert import convert_expression from slither.slithir.convert import convert_expression
from slither.slithir.operations import (Balance, HighLevelCall, Index, from slither.slithir.operations import (Balance, HighLevelCall, Index,
InternalCall, Length, LibraryCall, InternalCall, Length, LibraryCall,
LowLevelCall, Member, LowLevelCall, Member,
OperationWithLValue, Phi, PhiCallback, OperationWithLValue, Phi, PhiCallback,
SolidityCall) SolidityCall, Return)
from slither.slithir.variables import (Constant, LocalIRVariable, from slither.slithir.variables import (Constant, LocalIRVariable,
ReferenceVariable, StateIRVariable, ReferenceVariable, StateIRVariable,
TemporaryVariable, TupleVariable) TemporaryVariable, TupleVariable)
@ -424,11 +425,21 @@ class Node(SourceMapping, ChildFunction):
def is_conditional(self, include_loop=True): def is_conditional(self, include_loop=True):
""" """
Check if the node is a conditional node Check if the node is a conditional node
A conditional node is either a IF or a require/assert A conditional node is either a IF or a require/assert or a RETURN bool
Returns: Returns:
bool: True if the node is a conditional node bool: True if the node is a conditional node
""" """
return self.contains_if(include_loop) or self.contains_require_or_assert() if self.contains_if(include_loop) or self.contains_require_or_assert():
return True
if self.irs:
last_ir = self.irs[-1]
if last_ir:
if isinstance(last_ir, Return):
for r in last_ir.read:
if r.type == ElementaryType('bool'):
return True
return False
# endregion # endregion
@ -685,6 +696,8 @@ class Node(SourceMapping, ChildFunction):
elif isinstance(ir, (HighLevelCall)) and not isinstance(ir, LibraryCall): elif isinstance(ir, (HighLevelCall)) and not isinstance(ir, LibraryCall):
if isinstance(ir.destination.type, Contract): if isinstance(ir.destination.type, Contract):
self._high_level_calls.append((ir.destination.type, ir.function)) self._high_level_calls.append((ir.destination.type, ir.function))
elif ir.destination == SolidityVariable('this'):
self._high_level_calls.append((self.function.contract, ir.function))
else: else:
self._high_level_calls.append((ir.destination.type.type, ir.function)) self._high_level_calls.append((ir.destination.type.type, ir.function))
elif isinstance(ir, LibraryCall): elif isinstance(ir, LibraryCall):

@ -59,6 +59,8 @@ class Reentrancy(AbstractDetector):
# We can check that the function called is # We can check that the function called is
# reentrancy-safe # reentrancy-safe
if ir.destination == SolidityVariable('this'): if ir.destination == SolidityVariable('this'):
if isinstance(ir.function, Variable):
continue
if not ir.function.all_high_level_calls(): if not ir.function.all_high_level_calls():
if not ir.function.all_low_level_calls(): if not ir.function.all_low_level_calls():
continue continue

@ -142,6 +142,9 @@ class PrinterCallGraph(AbstractPrinter):
Args: Args:
filename(string) filename(string)
""" """
if not filename:
filename = "contracts.dot"
if not filename.endswith('.dot'): if not filename.endswith('.dot'):
filename += '.dot' filename += '.dot'

@ -171,7 +171,7 @@ class PrinterInheritanceGraph(AbstractPrinter):
filename(string) filename(string)
""" """
if filename == '': if filename == '':
filename = 'export' filename = 'contracts.dot'
if not filename.endswith('.dot'): if not filename.endswith('.dot'):
filename += ".dot" filename += ".dot"
info = 'Inheritance Graph: ' + filename info = 'Inheritance Graph: ' + filename

@ -1,6 +1,9 @@
import logging import logging
from slither.core.cfg.node import NodeType from slither.core.cfg.node import NodeType
from slither.core.declarations import (Contract, Enum, Function,
SolidityFunction, SolidityVariable,
SolidityVariableComposed, Structure)
from slither.core.variables.local_variable import LocalVariable from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.slithir.operations import (Assignment, Balance, Binary, Condition, from slither.slithir.operations import (Assignment, Balance, Binary, Condition,
@ -14,9 +17,10 @@ from slither.slithir.operations import (Assignment, Balance, Binary, Condition,
Push, Return, Send, SolidityCall, Push, Return, Send, SolidityCall,
Transfer, TypeConversion, Unary, Transfer, TypeConversion, Unary,
Unpack) Unpack)
from slither.slithir.variables import (LocalIRVariable, ReferenceVariable, from slither.slithir.variables import (Constant, LocalIRVariable,
ReferenceVariable, ReferenceVariableSSA,
StateIRVariable, TemporaryVariable, StateIRVariable, TemporaryVariable,
TupleVariable) TemporaryVariableSSA, TupleVariable, TupleVariableSSA)
logger = logging.getLogger('SSA_Conversion') logger = logging.getLogger('SSA_Conversion')
@ -164,6 +168,7 @@ def generate_ssa_irs(node, local_variables_instances, all_local_variables_instan
# They dont need phi function # They dont need phi function
temporary_variables_instances = dict() temporary_variables_instances = dict()
reference_variables_instances = dict() reference_variables_instances = dict()
tuple_variables_instances = dict()
for ir in node.irs: for ir in node.irs:
new_ir = copy_ir(ir, new_ir = copy_ir(ir,
@ -171,6 +176,7 @@ def generate_ssa_irs(node, local_variables_instances, all_local_variables_instan
state_variables_instances, state_variables_instances,
temporary_variables_instances, temporary_variables_instances,
reference_variables_instances, reference_variables_instances,
tuple_variables_instances,
all_local_variables_instances) all_local_variables_instances)
update_lvalue(new_ir, update_lvalue(new_ir,
@ -416,7 +422,81 @@ def add_phi_origins(node, local_variables_definition, state_variables_definition
################################################################################### ###################################################################################
################################################################################### ###################################################################################
def copy_ir(ir, local_variables_instances, state_variables_instances, temporary_variables_instances, reference_variables_instances, all_local_variables_instances): def get(variable, local_variables_instances, state_variables_instances, temporary_variables_instances, reference_variables_instances, tuple_variables_instances, all_local_variables_instances):
# variable can be None
# for example, on LowLevelCall, ir.lvalue can be none
if variable is None:
return None
if isinstance(variable, LocalVariable):
if variable.name in local_variables_instances:
return local_variables_instances[variable.name]
new_var = LocalIRVariable(variable)
local_variables_instances[variable.name] = new_var
all_local_variables_instances[variable.name] = new_var
return new_var
if isinstance(variable, StateVariable) and variable.canonical_name in state_variables_instances:
return state_variables_instances[variable.canonical_name]
elif isinstance(variable, ReferenceVariable):
if not variable.index in reference_variables_instances:
new_variable = ReferenceVariableSSA(variable)
if variable.points_to:
new_variable.points_to = get(variable.points_to,
local_variables_instances,
state_variables_instances,
temporary_variables_instances,
reference_variables_instances,
tuple_variables_instances,
all_local_variables_instances)
new_variable.set_type(variable.type)
reference_variables_instances[variable.index] = new_variable
return reference_variables_instances[variable.index]
elif isinstance(variable, TemporaryVariable):
if not variable.index in temporary_variables_instances:
new_variable = TemporaryVariableSSA(variable)
new_variable.set_type(variable.type)
temporary_variables_instances[variable.index] = new_variable
return temporary_variables_instances[variable.index]
elif isinstance(variable, TupleVariable):
if not variable.index in tuple_variables_instances:
new_variable = TupleVariableSSA(variable)
new_variable.set_type(variable.type)
tuple_variables_instances[variable.index] = new_variable
return tuple_variables_instances[variable.index]
assert isinstance(variable, (Constant,
SolidityVariable,
Contract,
Enum,
SolidityFunction,
Structure,
Function))
return variable
def get_variable(ir, f, *instances):
variable = f(ir)
variable = get(variable, *instances)
return variable
def _get_traversal(values, *instances):
ret = []
for v in values:
if isinstance(v, list):
v = _get_traversal(v, *instances)
else:
v = get(v, *instances)
ret.append(v)
return ret
def get_arguments(ir, *instances):
return _get_traversal(ir.arguments, *instances)
def get_rec_values(ir, f, *instances):
# Use by InitArray and NewArray
# Potential recursive array(s)
ori_init_values = f(ir)
return _get_traversal(ori_init_values, *instances)
def copy_ir(ir, *instances):
''' '''
Args: Args:
ir (Operation) ir (Operation)
@ -427,213 +507,156 @@ def copy_ir(ir, local_variables_instances, state_variables_instances, temporary_
Note: temporary and reference can be indexed by int, as they dont need phi functions Note: temporary and reference can be indexed by int, as they dont need phi functions
''' '''
def get(variable):
if isinstance(variable, LocalVariable):
if variable.name in local_variables_instances:
return local_variables_instances[variable.name]
new_var = LocalIRVariable(variable)
local_variables_instances[variable.name] = new_var
all_local_variables_instances[variable.name] = new_var
return new_var
if isinstance(variable, StateVariable) and variable.canonical_name in state_variables_instances:
return state_variables_instances[variable.canonical_name]
elif isinstance(variable, ReferenceVariable):
if not variable.index in reference_variables_instances:
new_variable = ReferenceVariable(variable.node, index=variable.index)
if variable.points_to:
new_variable.points_to = get(variable.points_to)
new_variable.set_type(variable.type)
reference_variables_instances[variable.index] = new_variable
return reference_variables_instances[variable.index]
elif isinstance(variable, TemporaryVariable):
if not variable.index in temporary_variables_instances:
new_variable = TemporaryVariable(variable.node, index=variable.index)
new_variable.set_type(variable.type)
temporary_variables_instances[variable.index] = new_variable
return temporary_variables_instances[variable.index]
return variable
def get_variable(ir, f):
variable = f(ir)
variable = get(variable)
return variable
def get_arguments(ir):
arguments = []
for arg in ir.arguments:
arg = get(arg)
arguments.append(arg)
return arguments
def get_rec_values(ir, f):
# Use by InitArray and NewArray
# Potential recursive array(s)
ori_init_values = f(ir)
def traversal(values):
ret = []
for v in values:
if isinstance(v, list):
v = traversal(v)
else:
v = get(v)
ret.append(v)
return ret
return traversal(ori_init_values)
if isinstance(ir, Assignment): if isinstance(ir, Assignment):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
rvalue = get_variable(ir, lambda x: ir.rvalue) rvalue = get_variable(ir, lambda x: x.rvalue, *instances)
variable_return_type = ir.variable_return_type variable_return_type = ir.variable_return_type
return Assignment(lvalue, rvalue, variable_return_type) return Assignment(lvalue, rvalue, variable_return_type)
elif isinstance(ir, Balance): elif isinstance(ir, Balance):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
value = get_variable(ir, lambda x: ir.value) value = get_variable(ir, lambda x: x.value, *instances)
return Balance(value, lvalue) return Balance(value, lvalue)
elif isinstance(ir, Binary): elif isinstance(ir, Binary):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable_left = get_variable(ir, lambda x: ir.variable_left) variable_left = get_variable(ir, lambda x: x.variable_left, *instances)
variable_right = get_variable(ir, lambda x: ir.variable_right) variable_right = get_variable(ir, lambda x: x.variable_right, *instances)
operation_type = ir.type operation_type = ir.type
return Binary(lvalue, variable_left, variable_right, operation_type) return Binary(lvalue, variable_left, variable_right, operation_type)
elif isinstance(ir, Condition): elif isinstance(ir, Condition):
val = get_variable(ir, lambda x: ir.value) val = get_variable(ir, lambda x: x.value, *instances)
return Condition(val) return Condition(val)
elif isinstance(ir, Delete): elif isinstance(ir, Delete):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable = get_variable(ir, lambda x: ir.variable) variable = get_variable(ir, lambda x: x.variable, *instances)
return Delete(lvalue, variable) return Delete(lvalue, variable)
elif isinstance(ir, EventCall): elif isinstance(ir, EventCall):
name = ir.name name = ir.name
return EventCall(name) return EventCall(name)
elif isinstance(ir, HighLevelCall): # include LibraryCall elif isinstance(ir, HighLevelCall): # include LibraryCall
destination = get_variable(ir, lambda x: ir.destination) destination = get_variable(ir, lambda x: x.destination, *instances)
function_name = ir.function_name function_name = ir.function_name
nbr_arguments = ir.nbr_arguments nbr_arguments = ir.nbr_arguments
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
type_call = ir.type_call type_call = ir.type_call
if isinstance(ir, LibraryCall): if isinstance(ir, LibraryCall):
new_ir = LibraryCall(destination, function_name, nbr_arguments, lvalue, type_call) new_ir = LibraryCall(destination, function_name, nbr_arguments, lvalue, type_call)
else: else:
new_ir = HighLevelCall(destination, function_name, nbr_arguments, lvalue, type_call) new_ir = HighLevelCall(destination, function_name, nbr_arguments, lvalue, type_call)
new_ir.call_id = ir.call_id new_ir.call_id = ir.call_id
new_ir.call_value = get_variable(ir, lambda x: ir.call_value) new_ir.call_value = get_variable(ir, lambda x: x.call_value, *instances)
new_ir.call_gas = get_variable(ir, lambda x: ir.call_gas) new_ir.call_gas = get_variable(ir, lambda x: x.call_gas, *instances)
new_ir.arguments = get_arguments(ir) new_ir.arguments = get_arguments(ir, *instances)
new_ir.function = ir.function new_ir.function = ir.function
return new_ir return new_ir
elif isinstance(ir, Index): elif isinstance(ir, Index):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable_left = get_variable(ir, lambda x: ir.variable_left) variable_left = get_variable(ir, lambda x: x.variable_left, *instances)
variable_right = get_variable(ir, lambda x: ir.variable_right) variable_right = get_variable(ir, lambda x: x.variable_right, *instances)
index_type = ir.index_type index_type = ir.index_type
return Index(lvalue, variable_left, variable_right, index_type) return Index(lvalue, variable_left, variable_right, index_type)
elif isinstance(ir, InitArray): elif isinstance(ir, InitArray):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
init_values = get_rec_values(ir, lambda x: ir.init_values) init_values = get_rec_values(ir, lambda x: x.init_values, *instances)
return InitArray(init_values, lvalue) return InitArray(init_values, lvalue)
elif isinstance(ir, InternalCall): elif isinstance(ir, InternalCall):
function = ir.function function = ir.function
nbr_arguments = ir.nbr_arguments nbr_arguments = ir.nbr_arguments
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
type_call = ir.type_call type_call = ir.type_call
new_ir = InternalCall(function, nbr_arguments, lvalue, type_call) new_ir = InternalCall(function, nbr_arguments, lvalue, type_call)
new_ir.arguments = get_arguments(ir) new_ir.arguments = get_arguments(ir, *instances)
return new_ir return new_ir
elif isinstance(ir, InternalDynamicCall): elif isinstance(ir, InternalDynamicCall):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
function = ir.function function = get_variable(ir, lambda x: x.function, *instances)
function_type = ir.function_type function_type = ir.function_type
new_ir = InternalDynamicCall(lvalue, function, function_type) new_ir = InternalDynamicCall(lvalue, function, function_type)
new_ir.arguments = get_arguments(ir) new_ir.arguments = get_arguments(ir, *instances)
return new_ir return new_ir
elif isinstance(ir, LowLevelCall): elif isinstance(ir, LowLevelCall):
destination = get_variable(ir, lambda x: x.destination) destination = get_variable(ir, lambda x: x.destination, *instances)
function_name = ir.function_name function_name = ir.function_name
nbr_arguments = ir.nbr_arguments nbr_arguments = ir.nbr_arguments
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
type_call = ir.type_call type_call = ir.type_call
new_ir = LowLevelCall(destination, function_name, nbr_arguments, lvalue, type_call) new_ir = LowLevelCall(destination, function_name, nbr_arguments, lvalue, type_call)
new_ir.call_id = ir.call_id new_ir.call_id = ir.call_id
new_ir.call_value = get_variable(ir, lambda x: ir.call_value) new_ir.call_value = get_variable(ir, lambda x: x.call_value, *instances)
new_ir.call_gas = get_variable(ir, lambda x: ir.call_gas) new_ir.call_gas = get_variable(ir, lambda x: x.call_gas, *instances)
new_ir.arguments = get_arguments(ir) new_ir.arguments = get_arguments(ir, *instances)
return new_ir return new_ir
elif isinstance(ir, Member): elif isinstance(ir, Member):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable_left = get_variable(ir, lambda x: ir.variable_left) variable_left = get_variable(ir, lambda x: x.variable_left, *instances)
variable_right = get_variable(ir, lambda x: ir.variable_right) variable_right = get_variable(ir, lambda x: x.variable_right, *instances)
return Member(variable_left, variable_right, lvalue) return Member(variable_left, variable_right, lvalue)
elif isinstance(ir, NewArray): elif isinstance(ir, NewArray):
depth = ir.depth depth = ir.depth
array_type = ir.array_type array_type = ir.array_type
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
new_ir = NewArray(depth, array_type, lvalue) new_ir = NewArray(depth, array_type, lvalue)
new_ir.arguments = get_rec_values(ir, lambda x: ir.arguments) new_ir.arguments = get_rec_values(ir, lambda x: x.arguments, *instances)
return new_ir return new_ir
elif isinstance(ir, NewElementaryType): elif isinstance(ir, NewElementaryType):
new_type = ir.type new_type = ir.type
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
new_ir = NewElementaryType(new_type, lvalue) new_ir = NewElementaryType(new_type, lvalue)
new_ir.arguments = get_arguments(ir) new_ir.arguments = get_arguments(ir, *instances)
return new_ir return new_ir
elif isinstance(ir, NewContract): elif isinstance(ir, NewContract):
contract_name = ir.contract_name contract_name = ir.contract_name
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
new_ir = NewContract(contract_name, lvalue) new_ir = NewContract(contract_name, lvalue)
new_ir.arguments = get_arguments(ir) new_ir.arguments = get_arguments(ir, *instances)
return new_ir return new_ir
elif isinstance(ir, NewStructure): elif isinstance(ir, NewStructure):
structure = ir.structure structure = ir.structure
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
new_ir = NewStructure(structure, lvalue) new_ir = NewStructure(structure, lvalue)
new_ir.arguments = get_arguments(ir) new_ir.arguments = get_arguments(ir, *instances)
return new_ir return new_ir
elif isinstance(ir, Push): elif isinstance(ir, Push):
array = get_variable(ir, lambda x: ir.array) array = get_variable(ir, lambda x: x.array, *instances)
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
return Push(array, lvalue) return Push(array, lvalue)
elif isinstance(ir, Return): elif isinstance(ir, Return):
value = [get_variable(x, lambda y: y) for x in ir.values] values = get_rec_values(ir, lambda x: x.values, *instances)
return Return(value) return Return(values)
elif isinstance(ir, Send): elif isinstance(ir, Send):
destination = get_variable(ir, lambda x: ir.destination) destination = get_variable(ir, lambda x: x.destination, *instances)
value = get_variable(ir, lambda x: ir.call_value) value = get_variable(ir, lambda x: x.call_value, *instances)
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
return Send(destination, value, lvalue) return Send(destination, value, lvalue)
elif isinstance(ir, SolidityCall): elif isinstance(ir, SolidityCall):
function = ir.function function = ir.function
nbr_arguments = ir.nbr_arguments nbr_arguments = ir.nbr_arguments
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
type_call = ir.type_call type_call = ir.type_call
new_ir = SolidityCall(function, nbr_arguments, lvalue, type_call) new_ir = SolidityCall(function, nbr_arguments, lvalue, type_call)
new_ir.arguments = get_arguments(ir) new_ir.arguments = get_arguments(ir, *instances)
return new_ir return new_ir
elif isinstance(ir, Transfer): elif isinstance(ir, Transfer):
destination = get_variable(ir, lambda x: ir.destination) destination = get_variable(ir, lambda x: x.destination, *instances)
value = get_variable(ir, lambda x: ir.call_value) value = get_variable(ir, lambda x: x.call_value, *instances)
return Transfer(destination, value) return Transfer(destination, value)
elif isinstance(ir, TypeConversion): elif isinstance(ir, TypeConversion):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable = get_variable(ir, lambda x: ir.variable) variable = get_variable(ir, lambda x: x.variable, *instances)
variable_type = ir.type variable_type = ir.type
return TypeConversion(lvalue, variable, variable_type) return TypeConversion(lvalue, variable, variable_type)
elif isinstance(ir, Unary): elif isinstance(ir, Unary):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
rvalue = get_variable(ir, lambda x: ir.rvalue) rvalue = get_variable(ir, lambda x: x.rvalue, *instances)
operation_type = ir.type operation_type = ir.type
return Unary(lvalue, rvalue, operation_type) return Unary(lvalue, rvalue, operation_type)
elif isinstance(ir, Unpack): elif isinstance(ir, Unpack):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
tuple_var = ir.tuple tuple_var = get_variable(ir, lambda x: x.tuple, *instances)
idx = ir.index idx = ir.index
return Unpack(lvalue, tuple_var, idx) return Unpack(lvalue, tuple_var, idx)
elif isinstance(ir, Length): elif isinstance(ir, Length):
lvalue = get_variable(ir, lambda x: ir.lvalue) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
value = get_variable(ir, lambda x: ir.value) value = get_variable(ir, lambda x: x.value, *instances)
return Length(value, lvalue) return Length(value, lvalue)

@ -1,6 +1,9 @@
from .constant import Constant from .constant import Constant
from .reference import ReferenceVariable from .reference import ReferenceVariable
from .reference_ssa import ReferenceVariableSSA
from .temporary import TemporaryVariable from .temporary import TemporaryVariable
from .temporary_ssa import TemporaryVariableSSA
from .tuple import TupleVariable from .tuple import TupleVariable
from .tuple_ssa import TupleVariableSSA
from .local_variable import LocalIRVariable from .local_variable import LocalIRVariable
from .state_variable import StateIRVariable from .state_variable import StateIRVariable

@ -0,0 +1,18 @@
'''
This class is used for the SSA version of slithIR
It is similar to the non-SSA version of slithIR
as the ReferenceVariable are in SSA form in both version
'''
from .reference import ReferenceVariable
from .variable import SlithIRVariable
class ReferenceVariableSSA(ReferenceVariable):
def __init__(self, reference):
super(ReferenceVariableSSA, self).__init__(reference.node, reference.index)
self._non_ssa_version = reference
@property
def non_ssa_version(self):
return self._non_ssa_version

@ -0,0 +1,20 @@
'''
This class is used for the SSA version of slithIR
It is similar to the non-SSA version of slithIR
as the TemporaryVariable are in SSA form in both version
'''
from .temporary import TemporaryVariable
from .variable import SlithIRVariable
class TemporaryVariableSSA(TemporaryVariable):
def __init__(self, temporary):
super(TemporaryVariableSSA, self).__init__(temporary.node, temporary.index)
self._non_ssa_version = temporary
@property
def non_ssa_version(self):
return self._non_ssa_version

@ -1,15 +1,21 @@
from .variable import SlithIRVariable from .variable import SlithIRVariable
from slither.core.variables.variable import Variable from slither.core.variables.variable import Variable
from slither.core.children.child_node import ChildNode
from slither.core.solidity_types.type import Type from slither.core.solidity_types.type import Type
class TupleVariable(SlithIRVariable): class TupleVariable(ChildNode, SlithIRVariable):
COUNTER = 0 COUNTER = 0
def __init__(self): def __init__(self, node, index=None):
super(TupleVariable, self).__init__() super(TupleVariable, self).__init__()
self._index = TupleVariable.COUNTER if index is None:
TupleVariable.COUNTER += 1 self._index = TupleVariable.COUNTER
TupleVariable.COUNTER += 1
else:
self._index = index
self._node = node
@property @property
def index(self): def index(self):

@ -0,0 +1,20 @@
'''
This class is used for the SSA version of slithIR
It is similar to the non-SSA version of slithIR
as the TupleVariable are in SSA form in both version
'''
from .tuple import TupleVariable
from .variable import SlithIRVariable
class TupleVariableSSA(TupleVariable):
def __init__(self, t):
super(TupleVariableSSA, self).__init__(t.node, t.index)
self._non_ssa_version = t
@property
def non_ssa_version(self):
return self._non_ssa_version

@ -160,7 +160,10 @@ def parse_type(t, caller_context):
elif t[key] == 'UserDefinedTypeName': elif t[key] == 'UserDefinedTypeName':
if is_compact_ast: if is_compact_ast:
return _find_from_type_name(t['typeDescriptions']['typeString'], contract, contracts, structures, enums) return _find_from_type_name(t['typeDescriptions']['typeString'], contract, contracts, structures, enums)
return _find_from_type_name(t['attributes'][key], contract, contracts, structures, enums)
# Determine if we have a type node (otherwise we use the name node, as some older solc did not have 'type').
type_name_key = 'type' if 'type' in t['attributes'] else key
return _find_from_type_name(t['attributes'][type_name_key], contract, contracts, structures, enums)
elif t[key] == 'ArrayTypeName': elif t[key] == 'ArrayTypeName':
length = None length = None

@ -128,7 +128,7 @@ class ExpressionToSlithIR(ExpressionVisitor):
# If tuple # If tuple
if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()': if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()':
val = TupleVariable() val = TupleVariable(self._node)
else: else:
val = TemporaryVariable(self._node) val = TemporaryVariable(self._node)
internal_call = InternalCall(called, len(args), val, expression.type_call) internal_call = InternalCall(called, len(args), val, expression.type_call)
@ -139,7 +139,7 @@ class ExpressionToSlithIR(ExpressionVisitor):
# If tuple # If tuple
if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()': if expression.type_call.startswith('tuple(') and expression.type_call != 'tuple()':
val = TupleVariable() val = TupleVariable(self._node)
else: else:
val = TemporaryVariable(self._node) val = TemporaryVariable(self._node)

Loading…
Cancel
Save