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)
if 'devDependencies' in package:
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']
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)

@ -1,13 +1,14 @@
"""
Compute the data depenency between all the SSA variables
"""
from slither.core.declarations import Contract, Function
from slither.core.declarations.solidity_variables import \
SolidityVariableComposed
from slither.core.declarations import (Contract, Enum, Function,
SolidityFunction, SolidityVariable,
SolidityVariableComposed, Structure)
from slither.slithir.operations import Index, OperationWithLValue
from slither.slithir.variables import (Constant, LocalIRVariable,
ReferenceVariable, StateIRVariable,
TemporaryVariable)
ReferenceVariable, ReferenceVariableSSA,
StateIRVariable, TemporaryVariable,
TemporaryVariableSSA, TupleVariableSSA)
###################################################################################
###################################################################################
@ -243,7 +244,6 @@ def compute_dependency_function(function):
function.context[KEY_SSA_UNPROTECTED] = dict()
is_protected = function.is_protected()
for node in function.nodes:
for ir in node.irs_ssa:
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])
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
if isinstance(v, (TemporaryVariable, ReferenceVariable)):
return next((variable for variable in v.function.slithir_variables if variable.name == v.name))
assert isinstance(v, (Constant, SolidityVariable, Contract, Enum, SolidityFunction, Structure, Function))
return v
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.state_variable import StateVariable
from slither.core.variables.variable import Variable
from slither.core.solidity_types import ElementaryType
from slither.slithir.convert import convert_expression
from slither.slithir.operations import (Balance, HighLevelCall, Index,
InternalCall, Length, LibraryCall,
LowLevelCall, Member,
OperationWithLValue, Phi, PhiCallback,
SolidityCall)
SolidityCall, Return)
from slither.slithir.variables import (Constant, LocalIRVariable,
ReferenceVariable, StateIRVariable,
TemporaryVariable, TupleVariable)
@ -424,11 +425,21 @@ class Node(SourceMapping, ChildFunction):
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
A conditional node is either a IF or a require/assert or a RETURN bool
Returns:
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
@ -685,6 +696,8 @@ class Node(SourceMapping, ChildFunction):
elif isinstance(ir, (HighLevelCall)) and not isinstance(ir, LibraryCall):
if isinstance(ir.destination.type, Contract):
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:
self._high_level_calls.append((ir.destination.type.type, ir.function))
elif isinstance(ir, LibraryCall):

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

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

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

@ -1,6 +1,9 @@
import logging
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.state_variable import StateVariable
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,
Transfer, TypeConversion, Unary,
Unpack)
from slither.slithir.variables import (LocalIRVariable, ReferenceVariable,
from slither.slithir.variables import (Constant, LocalIRVariable,
ReferenceVariable, ReferenceVariableSSA,
StateIRVariable, TemporaryVariable,
TupleVariable)
TemporaryVariableSSA, TupleVariable, TupleVariableSSA)
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
temporary_variables_instances = dict()
reference_variables_instances = dict()
tuple_variables_instances = dict()
for ir in node.irs:
new_ir = copy_ir(ir,
@ -171,6 +176,7 @@ def generate_ssa_irs(node, local_variables_instances, all_local_variables_instan
state_variables_instances,
temporary_variables_instances,
reference_variables_instances,
tuple_variables_instances,
all_local_variables_instances)
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:
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
'''
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):
lvalue = get_variable(ir, lambda x: ir.lvalue)
rvalue = get_variable(ir, lambda x: ir.rvalue)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
rvalue = get_variable(ir, lambda x: x.rvalue, *instances)
variable_return_type = ir.variable_return_type
return Assignment(lvalue, rvalue, variable_return_type)
elif isinstance(ir, Balance):
lvalue = get_variable(ir, lambda x: ir.lvalue)
value = get_variable(ir, lambda x: ir.value)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
value = get_variable(ir, lambda x: x.value, *instances)
return Balance(value, lvalue)
elif isinstance(ir, Binary):
lvalue = get_variable(ir, lambda x: ir.lvalue)
variable_left = get_variable(ir, lambda x: ir.variable_left)
variable_right = get_variable(ir, lambda x: ir.variable_right)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable_left = get_variable(ir, lambda x: x.variable_left, *instances)
variable_right = get_variable(ir, lambda x: x.variable_right, *instances)
operation_type = ir.type
return Binary(lvalue, variable_left, variable_right, operation_type)
elif isinstance(ir, Condition):
val = get_variable(ir, lambda x: ir.value)
val = get_variable(ir, lambda x: x.value, *instances)
return Condition(val)
elif isinstance(ir, Delete):
lvalue = get_variable(ir, lambda x: ir.lvalue)
variable = get_variable(ir, lambda x: ir.variable)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable = get_variable(ir, lambda x: x.variable, *instances)
return Delete(lvalue, variable)
elif isinstance(ir, EventCall):
name = ir.name
return EventCall(name)
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
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
if isinstance(ir, LibraryCall):
new_ir = LibraryCall(destination, function_name, nbr_arguments, lvalue, type_call)
else:
new_ir = HighLevelCall(destination, function_name, nbr_arguments, lvalue, type_call)
new_ir.call_id = ir.call_id
new_ir.call_value = get_variable(ir, lambda x: ir.call_value)
new_ir.call_gas = get_variable(ir, lambda x: ir.call_gas)
new_ir.arguments = get_arguments(ir)
new_ir.call_value = get_variable(ir, lambda x: x.call_value, *instances)
new_ir.call_gas = get_variable(ir, lambda x: x.call_gas, *instances)
new_ir.arguments = get_arguments(ir, *instances)
new_ir.function = ir.function
return new_ir
elif isinstance(ir, Index):
lvalue = get_variable(ir, lambda x: ir.lvalue)
variable_left = get_variable(ir, lambda x: ir.variable_left)
variable_right = get_variable(ir, lambda x: ir.variable_right)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable_left = get_variable(ir, lambda x: x.variable_left, *instances)
variable_right = get_variable(ir, lambda x: x.variable_right, *instances)
index_type = ir.index_type
return Index(lvalue, variable_left, variable_right, index_type)
elif isinstance(ir, InitArray):
lvalue = get_variable(ir, lambda x: ir.lvalue)
init_values = get_rec_values(ir, lambda x: ir.init_values)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
init_values = get_rec_values(ir, lambda x: x.init_values, *instances)
return InitArray(init_values, lvalue)
elif isinstance(ir, InternalCall):
function = ir.function
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
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
elif isinstance(ir, InternalDynamicCall):
lvalue = get_variable(ir, lambda x: ir.lvalue)
function = ir.function
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
function = get_variable(ir, lambda x: x.function, *instances)
function_type = ir.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
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
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
new_ir = LowLevelCall(destination, function_name, nbr_arguments, lvalue, type_call)
new_ir.call_id = ir.call_id
new_ir.call_value = get_variable(ir, lambda x: ir.call_value)
new_ir.call_gas = get_variable(ir, lambda x: ir.call_gas)
new_ir.arguments = get_arguments(ir)
new_ir.call_value = get_variable(ir, lambda x: x.call_value, *instances)
new_ir.call_gas = get_variable(ir, lambda x: x.call_gas, *instances)
new_ir.arguments = get_arguments(ir, *instances)
return new_ir
elif isinstance(ir, Member):
lvalue = get_variable(ir, lambda x: ir.lvalue)
variable_left = get_variable(ir, lambda x: ir.variable_left)
variable_right = get_variable(ir, lambda x: ir.variable_right)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable_left = get_variable(ir, lambda x: x.variable_left, *instances)
variable_right = get_variable(ir, lambda x: x.variable_right, *instances)
return Member(variable_left, variable_right, lvalue)
elif isinstance(ir, NewArray):
depth = ir.depth
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.arguments = get_rec_values(ir, lambda x: ir.arguments)
new_ir.arguments = get_rec_values(ir, lambda x: x.arguments, *instances)
return new_ir
elif isinstance(ir, NewElementaryType):
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.arguments = get_arguments(ir)
new_ir.arguments = get_arguments(ir, *instances)
return new_ir
elif isinstance(ir, NewContract):
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.arguments = get_arguments(ir)
new_ir.arguments = get_arguments(ir, *instances)
return new_ir
elif isinstance(ir, NewStructure):
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.arguments = get_arguments(ir)
new_ir.arguments = get_arguments(ir, *instances)
return new_ir
elif isinstance(ir, Push):
array = get_variable(ir, lambda x: ir.array)
lvalue = get_variable(ir, lambda x: ir.lvalue)
array = get_variable(ir, lambda x: x.array, *instances)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
return Push(array, lvalue)
elif isinstance(ir, Return):
value = [get_variable(x, lambda y: y) for x in ir.values]
return Return(value)
values = get_rec_values(ir, lambda x: x.values, *instances)
return Return(values)
elif isinstance(ir, Send):
destination = get_variable(ir, lambda x: ir.destination)
value = get_variable(ir, lambda x: ir.call_value)
lvalue = get_variable(ir, lambda x: ir.lvalue)
destination = get_variable(ir, lambda x: x.destination, *instances)
value = get_variable(ir, lambda x: x.call_value, *instances)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
return Send(destination, value, lvalue)
elif isinstance(ir, SolidityCall):
function = ir.function
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
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
elif isinstance(ir, Transfer):
destination = get_variable(ir, lambda x: ir.destination)
value = get_variable(ir, lambda x: ir.call_value)
destination = get_variable(ir, lambda x: x.destination, *instances)
value = get_variable(ir, lambda x: x.call_value, *instances)
return Transfer(destination, value)
elif isinstance(ir, TypeConversion):
lvalue = get_variable(ir, lambda x: ir.lvalue)
variable = get_variable(ir, lambda x: ir.variable)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable = get_variable(ir, lambda x: x.variable, *instances)
variable_type = ir.type
return TypeConversion(lvalue, variable, variable_type)
elif isinstance(ir, Unary):
lvalue = get_variable(ir, lambda x: ir.lvalue)
rvalue = get_variable(ir, lambda x: ir.rvalue)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
rvalue = get_variable(ir, lambda x: x.rvalue, *instances)
operation_type = ir.type
return Unary(lvalue, rvalue, operation_type)
elif isinstance(ir, Unpack):
lvalue = get_variable(ir, lambda x: ir.lvalue)
tuple_var = ir.tuple
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
tuple_var = get_variable(ir, lambda x: x.tuple, *instances)
idx = ir.index
return Unpack(lvalue, tuple_var, idx)
elif isinstance(ir, Length):
lvalue = get_variable(ir, lambda x: ir.lvalue)
value = get_variable(ir, lambda x: ir.value)
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
value = get_variable(ir, lambda x: x.value, *instances)
return Length(value, lvalue)

@ -1,6 +1,9 @@
from .constant import Constant
from .reference import ReferenceVariable
from .reference_ssa import ReferenceVariableSSA
from .temporary import TemporaryVariable
from .temporary_ssa import TemporaryVariableSSA
from .tuple import TupleVariable
from .tuple_ssa import TupleVariableSSA
from .local_variable import LocalIRVariable
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 slither.core.variables.variable import Variable
from slither.core.children.child_node import ChildNode
from slither.core.solidity_types.type import Type
class TupleVariable(SlithIRVariable):
class TupleVariable(ChildNode, SlithIRVariable):
COUNTER = 0
def __init__(self):
def __init__(self, node, index=None):
super(TupleVariable, self).__init__()
self._index = TupleVariable.COUNTER
TupleVariable.COUNTER += 1
if index is None:
self._index = TupleVariable.COUNTER
TupleVariable.COUNTER += 1
else:
self._index = index
self._node = node
@property
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':
if is_compact_ast:
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':
length = None

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

Loading…
Cancel
Save