|
|
|
@ -29,25 +29,46 @@ class FunctionSolc(Function): |
|
|
|
|
""" |
|
|
|
|
# elems = [(type, name)] |
|
|
|
|
|
|
|
|
|
def __init__(self, function): |
|
|
|
|
def __init__(self, function, contract): |
|
|
|
|
super(FunctionSolc, self).__init__() |
|
|
|
|
self._name = function['attributes']['name'] |
|
|
|
|
self._contract = contract |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
self._name = function['name'] |
|
|
|
|
else: |
|
|
|
|
self._name = function['attributes'][self.get_key()] |
|
|
|
|
self._functionNotParsed = function |
|
|
|
|
self._params_was_analyzed = False |
|
|
|
|
self._content_was_analyzed = False |
|
|
|
|
self._counter_nodes = 0 |
|
|
|
|
|
|
|
|
|
def get_key(self): |
|
|
|
|
return self.slither.get_key() |
|
|
|
|
|
|
|
|
|
def get_children(self, key): |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
return key |
|
|
|
|
return 'children' |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def is_compact_ast(self): |
|
|
|
|
return self.slither.is_compact_ast |
|
|
|
|
|
|
|
|
|
def _analyze_attributes(self): |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
attributes = self._functionNotParsed |
|
|
|
|
else: |
|
|
|
|
attributes = self._functionNotParsed['attributes'] |
|
|
|
|
|
|
|
|
|
if 'payable' in attributes: |
|
|
|
|
self._payable = attributes['payable'] |
|
|
|
|
elif 'stateMutability' in attributes: |
|
|
|
|
if 'stateMutability' in attributes: |
|
|
|
|
if attributes['stateMutability'] == 'payable': |
|
|
|
|
self._payable = True |
|
|
|
|
elif attributes['stateMutability'] == 'pure': |
|
|
|
|
self._pure = True |
|
|
|
|
self._view = True |
|
|
|
|
elif attributes['stateMutability'] == 'view': |
|
|
|
|
self._view = True |
|
|
|
|
|
|
|
|
|
if 'constant' in attributes: |
|
|
|
|
self._view = attributes['constant'] |
|
|
|
@ -80,43 +101,79 @@ class FunctionSolc(Function): |
|
|
|
|
|
|
|
|
|
def _parse_if(self, ifStatement, node): |
|
|
|
|
# IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? |
|
|
|
|
falseStatement = None |
|
|
|
|
|
|
|
|
|
children = ifStatement['children'] |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
condition = ifStatement['condition'] |
|
|
|
|
# Note: check if the expression could be directly |
|
|
|
|
# parsed here |
|
|
|
|
condition_node = self._new_node(NodeType.IF) |
|
|
|
|
#condition = parse_expression(children[0], self) |
|
|
|
|
condition_node.add_unparsed_expression(condition) |
|
|
|
|
link_nodes(node, condition_node) |
|
|
|
|
trueStatement = self._parse_statement(ifStatement['trueBody'], condition_node) |
|
|
|
|
if ifStatement['falseBody']: |
|
|
|
|
falseStatement = self._parse_statement(ifStatement['falseBody'], condition_node) |
|
|
|
|
else: |
|
|
|
|
children = ifStatement[self.get_children('children')] |
|
|
|
|
condition = children[0] |
|
|
|
|
# Note: check if the expression could be directly |
|
|
|
|
# parsed here |
|
|
|
|
condition_node = self._new_node(NodeType.IF) |
|
|
|
|
condition_node.add_unparsed_expression(condition) |
|
|
|
|
|
|
|
|
|
link_nodes(node, condition_node) |
|
|
|
|
|
|
|
|
|
trueStatement = self._parse_statement(children[1], condition_node) |
|
|
|
|
|
|
|
|
|
if len(children) == 3: |
|
|
|
|
falseStatement = self._parse_statement(children[2], condition_node) |
|
|
|
|
|
|
|
|
|
endIf_node = self._new_node(NodeType.ENDIF) |
|
|
|
|
link_nodes(trueStatement, endIf_node) |
|
|
|
|
|
|
|
|
|
if len(children) == 3: |
|
|
|
|
falseStatement = self._parse_statement(children[2], condition_node) |
|
|
|
|
|
|
|
|
|
if falseStatement: |
|
|
|
|
link_nodes(falseStatement, endIf_node) |
|
|
|
|
|
|
|
|
|
else: |
|
|
|
|
link_nodes(condition_node, endIf_node) |
|
|
|
|
|
|
|
|
|
return endIf_node |
|
|
|
|
|
|
|
|
|
# def _parse_if(self, ifStatement, node): |
|
|
|
|
# # IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? |
|
|
|
|
# |
|
|
|
|
# children = ifStatement[self.get_children('children')] |
|
|
|
|
# condition_node = self._new_node(NodeType.IF) |
|
|
|
|
# #condition = parse_expression(children[0], self) |
|
|
|
|
# condition = children[0] |
|
|
|
|
# condition_node.add_unparsed_expression(condition) |
|
|
|
|
# |
|
|
|
|
# link_nodes(node, condition_node) |
|
|
|
|
# |
|
|
|
|
# trueStatement = self._parse_statement(children[1], condition_node) |
|
|
|
|
# |
|
|
|
|
# |
|
|
|
|
# endIf_node = self._new_node(NodeType.ENDIF) |
|
|
|
|
# link_nodes(trueStatement, endIf_node) |
|
|
|
|
# |
|
|
|
|
# if len(children) == 3: |
|
|
|
|
# falseStatement = self._parse_statement(children[2], condition_node) |
|
|
|
|
# |
|
|
|
|
# link_nodes(falseStatement, endIf_node) |
|
|
|
|
# |
|
|
|
|
# else: |
|
|
|
|
# link_nodes(condition_node, endIf_node) |
|
|
|
|
# |
|
|
|
|
# return endIf_node |
|
|
|
|
|
|
|
|
|
def _parse_while(self, whileStatement, node): |
|
|
|
|
# WhileStatement = 'while' '(' Expression ')' Statement |
|
|
|
|
|
|
|
|
|
children = whileStatement['children'] |
|
|
|
|
|
|
|
|
|
node_startWhile = self._new_node(NodeType.STARTLOOP) |
|
|
|
|
|
|
|
|
|
node_condition = self._new_node(NodeType.IFLOOP) |
|
|
|
|
#expression = parse_expression(children[0], self) |
|
|
|
|
|
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
node_condition.add_unparsed_expression(whileStatement['condition']) |
|
|
|
|
statement = self._parse_statement(whileStatement['body'], node_condition) |
|
|
|
|
else: |
|
|
|
|
children = whileStatement[self.get_children('children')] |
|
|
|
|
expression = children[0] |
|
|
|
|
node_condition.add_unparsed_expression(expression) |
|
|
|
|
|
|
|
|
|
statement = self._parse_statement(children[1], node_condition) |
|
|
|
|
|
|
|
|
|
node_endWhile = self._new_node(NodeType.ENDLOOP) |
|
|
|
@ -128,9 +185,56 @@ class FunctionSolc(Function): |
|
|
|
|
|
|
|
|
|
return node_endWhile |
|
|
|
|
|
|
|
|
|
def _parse_for_compact_ast(self, statement, node): |
|
|
|
|
body = statement['body'] |
|
|
|
|
init_expression = statement['initializationExpression'] |
|
|
|
|
condition = statement['condition'] |
|
|
|
|
loop_expression = statement['loopExpression'] |
|
|
|
|
|
|
|
|
|
node_startLoop = self._new_node(NodeType.STARTLOOP) |
|
|
|
|
node_endLoop = self._new_node(NodeType.ENDLOOP) |
|
|
|
|
|
|
|
|
|
if init_expression: |
|
|
|
|
node_init_expression = self._parse_statement(init_expression, node) |
|
|
|
|
link_nodes(node_init_expression, node_startLoop) |
|
|
|
|
else: |
|
|
|
|
link_nodes(node, node_startLoop) |
|
|
|
|
|
|
|
|
|
if condition: |
|
|
|
|
node_condition = self._new_node(NodeType.IFLOOP) |
|
|
|
|
node_condition.add_unparsed_expression(condition) |
|
|
|
|
link_nodes(node_startLoop, node_condition) |
|
|
|
|
link_nodes(node_condition, node_endLoop) |
|
|
|
|
else: |
|
|
|
|
node_condition = node_startLoop |
|
|
|
|
|
|
|
|
|
node_body = self._parse_statement(body, node_condition) |
|
|
|
|
|
|
|
|
|
if loop_expression: |
|
|
|
|
node_LoopExpression = self._parse_statement(loop_expression, node_body) |
|
|
|
|
link_nodes(node_LoopExpression, node_startLoop) |
|
|
|
|
else: |
|
|
|
|
link_nodes(node_body, node_startLoop) |
|
|
|
|
|
|
|
|
|
if not condition: |
|
|
|
|
if not loop_expression: |
|
|
|
|
# TODO: fix case where loop has no expression |
|
|
|
|
link_nodes(node_startLoop, node_endLoop) |
|
|
|
|
else: |
|
|
|
|
link_nodes(node_LoopExpression, node_endLoop) |
|
|
|
|
|
|
|
|
|
return node_endLoop |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _parse_for(self, statement, node): |
|
|
|
|
# ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement |
|
|
|
|
|
|
|
|
|
# the handling of loop in the legacy ast is too complex |
|
|
|
|
# to integrate the comapct ast |
|
|
|
|
# its cleaner to do it separately |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
return self._parse_for_compact_ast(statement, node) |
|
|
|
|
|
|
|
|
|
hasInitExession = True |
|
|
|
|
hasCondition = True |
|
|
|
|
hasLoopExpression = True |
|
|
|
@ -153,11 +257,11 @@ class FunctionSolc(Function): |
|
|
|
|
node_startLoop = self._new_node(NodeType.STARTLOOP) |
|
|
|
|
node_endLoop = self._new_node(NodeType.ENDLOOP) |
|
|
|
|
|
|
|
|
|
children = statement['children'] |
|
|
|
|
children = statement[self.get_children('children')] |
|
|
|
|
|
|
|
|
|
if hasInitExession: |
|
|
|
|
if len(children) >= 2: |
|
|
|
|
if children[0]['name'] in ['VariableDefinitionStatement', |
|
|
|
|
if children[0][self.get_key()] in ['VariableDefinitionStatement', |
|
|
|
|
'VariableDeclarationStatement', |
|
|
|
|
'ExpressionStatement']: |
|
|
|
|
node_initExpression = self._parse_statement(children[0], node) |
|
|
|
@ -176,7 +280,7 @@ class FunctionSolc(Function): |
|
|
|
|
candidate = children[1] |
|
|
|
|
else: |
|
|
|
|
candidate = children[0] |
|
|
|
|
if candidate['name'] not in ['VariableDefinitionStatement', |
|
|
|
|
if candidate[self.get_key()] not in ['VariableDefinitionStatement', |
|
|
|
|
'VariableDeclarationStatement', |
|
|
|
|
'ExpressionStatement']: |
|
|
|
|
node_condition = self._new_node(NodeType.IFLOOP) |
|
|
|
@ -195,42 +299,45 @@ class FunctionSolc(Function): |
|
|
|
|
node_LoopExpression = node_statement |
|
|
|
|
if hasLoopExpression: |
|
|
|
|
if len(children) > 2: |
|
|
|
|
if children[-2]['name'] == 'ExpressionStatement': |
|
|
|
|
if children[-2][self.get_key()] == 'ExpressionStatement': |
|
|
|
|
node_LoopExpression = self._parse_statement(children[-2], node_statement) |
|
|
|
|
if not hasCondition: |
|
|
|
|
link_nodes(node_LoopExpression, node_endLoop) |
|
|
|
|
|
|
|
|
|
if not hasCondition and not hasLoopExpression: |
|
|
|
|
link_nodes(node, node_endLoop) |
|
|
|
|
|
|
|
|
|
link_nodes(node_LoopExpression, node_startLoop) |
|
|
|
|
|
|
|
|
|
return node_endLoop |
|
|
|
|
|
|
|
|
|
def _parse_dowhile(self, doWhilestatement, node): |
|
|
|
|
children = doWhilestatement['children'] |
|
|
|
|
|
|
|
|
|
node_startDoWhile = self._new_node(NodeType.STARTLOOP) |
|
|
|
|
node_condition = self._new_node(NodeType.IFLOOP) |
|
|
|
|
|
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
node_condition.add_unparsed_expression(doWhilestatement['condition']) |
|
|
|
|
statement = self._parse_statement(doWhilestatement['body'], node_condition) |
|
|
|
|
else: |
|
|
|
|
children = doWhilestatement[self.get_children('children')] |
|
|
|
|
# same order in the AST as while |
|
|
|
|
node_condition = self._new_node(NodeType.IFLOOP) |
|
|
|
|
#expression = parse_expression(children[0], self) |
|
|
|
|
expression = children[0] |
|
|
|
|
node_condition.add_unparsed_expression(expression) |
|
|
|
|
|
|
|
|
|
statement = self._parse_statement(children[1], node_condition) |
|
|
|
|
|
|
|
|
|
node_endDoWhile = self._new_node(NodeType.ENDLOOP) |
|
|
|
|
|
|
|
|
|
link_nodes(node, node_startDoWhile) |
|
|
|
|
link_nodes(node_startDoWhile, node_condition) |
|
|
|
|
link_nodes(node_startDoWhile, statement) |
|
|
|
|
link_nodes(statement, node_condition) |
|
|
|
|
link_nodes(node_condition, node_endDoWhile) |
|
|
|
|
|
|
|
|
|
return node_endDoWhile |
|
|
|
|
|
|
|
|
|
def _parse_variable_definition(self, statement, node): |
|
|
|
|
#assert len(statement['children']) == 1 |
|
|
|
|
# if there is, parse default value |
|
|
|
|
#assert not 'attributes' in statement |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
local_var = LocalVariableSolc(statement) |
|
|
|
|
#local_var = LocalVariableSolc(statement['children'][0], statement['children'][1::]) |
|
|
|
|
local_var.set_function(self) |
|
|
|
|
local_var.set_offset(statement['src'], self.contract.slither) |
|
|
|
|
|
|
|
|
@ -243,10 +350,84 @@ class FunctionSolc(Function): |
|
|
|
|
return new_node |
|
|
|
|
except MultipleVariablesDeclaration: |
|
|
|
|
# Custom handling of var (a,b) = .. style declaration |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
variables = statement['declarations'] |
|
|
|
|
count = len(variables) |
|
|
|
|
|
|
|
|
|
if statement['initialValue']['nodeType'] == 'TupleExpression': |
|
|
|
|
inits = statement['initialValue']['components'] |
|
|
|
|
i = 0 |
|
|
|
|
new_node = node |
|
|
|
|
for variable in variables: |
|
|
|
|
init = inits[i] |
|
|
|
|
src = variable['src'] |
|
|
|
|
i = i+1 |
|
|
|
|
|
|
|
|
|
new_statement = {'nodeType':'VariableDefinitionStatement', |
|
|
|
|
'src': src, |
|
|
|
|
'declarations':[variable], |
|
|
|
|
'initialValue':init} |
|
|
|
|
new_node = self._parse_variable_definition(new_statement, new_node) |
|
|
|
|
|
|
|
|
|
else: |
|
|
|
|
# If we have |
|
|
|
|
# var (a, b) = f() |
|
|
|
|
# we can split in multiple declarations, without init |
|
|
|
|
# Then we craft one expression that does the assignment |
|
|
|
|
variables = [] |
|
|
|
|
i = 0 |
|
|
|
|
new_node = node |
|
|
|
|
for variable in statement['declarations']: |
|
|
|
|
i = i+1 |
|
|
|
|
if variable: |
|
|
|
|
src = variable['src'] |
|
|
|
|
# Create a fake statement to be consistent |
|
|
|
|
new_statement = {'nodeType':'VariableDefinitionStatement', |
|
|
|
|
'src': src, |
|
|
|
|
'declarations':[variable]} |
|
|
|
|
variables.append(variable) |
|
|
|
|
|
|
|
|
|
new_node = self._parse_variable_definition_init_tuple(new_statement, |
|
|
|
|
i, |
|
|
|
|
new_node) |
|
|
|
|
|
|
|
|
|
var_identifiers = [] |
|
|
|
|
# craft of the expression doing the assignement |
|
|
|
|
for v in variables: |
|
|
|
|
identifier = { |
|
|
|
|
'nodeType':'Identifier', |
|
|
|
|
'src': v['src'], |
|
|
|
|
'name': v['name'], |
|
|
|
|
'typeDescriptions': { |
|
|
|
|
'typeString':v['typeDescriptions']['typeString'] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
var_identifiers.append(identifier) |
|
|
|
|
|
|
|
|
|
tuple_expression = {'nodeType':'TupleExpression', |
|
|
|
|
'src': statement['src'], |
|
|
|
|
'components':var_identifiers} |
|
|
|
|
|
|
|
|
|
expression = { |
|
|
|
|
'nodeType' : 'Assignment', |
|
|
|
|
'src':statement['src'], |
|
|
|
|
'operator': '=', |
|
|
|
|
'type':'tuple()', |
|
|
|
|
'leftHandSide': tuple_expression, |
|
|
|
|
'rightHandSide': statement['initialValue'], |
|
|
|
|
'typeDescriptions': {'typeString':'tuple()'} |
|
|
|
|
} |
|
|
|
|
node = new_node |
|
|
|
|
new_node = self._new_node(NodeType.EXPRESSION) |
|
|
|
|
new_node.add_unparsed_expression(expression) |
|
|
|
|
link_nodes(node, new_node) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else: |
|
|
|
|
count = 0 |
|
|
|
|
children = statement['children'] |
|
|
|
|
children = statement[self.get_children('children')] |
|
|
|
|
child = children[0] |
|
|
|
|
while child['name'] == 'VariableDeclaration': |
|
|
|
|
while child[self.get_key()] == 'VariableDeclaration': |
|
|
|
|
count = count +1 |
|
|
|
|
child = children[count] |
|
|
|
|
|
|
|
|
@ -257,32 +438,32 @@ class FunctionSolc(Function): |
|
|
|
|
variables_declaration = children[0:count] |
|
|
|
|
i = 0 |
|
|
|
|
new_node = node |
|
|
|
|
if tuple_vars['name'] == 'TupleExpression': |
|
|
|
|
assert len(tuple_vars['children']) == count |
|
|
|
|
if tuple_vars[self.get_key()] == 'TupleExpression': |
|
|
|
|
assert len(tuple_vars[self.get_children('children')]) == count |
|
|
|
|
for variable in variables_declaration: |
|
|
|
|
init = tuple_vars['children'][i] |
|
|
|
|
init = tuple_vars[self.get_children('children')][i] |
|
|
|
|
src = variable['src'] |
|
|
|
|
i= i+1 |
|
|
|
|
i = i+1 |
|
|
|
|
# Create a fake statement to be consistent |
|
|
|
|
new_statement = {'name':'VariableDefinitionStatement', |
|
|
|
|
new_statement = {self.get_key():'VariableDefinitionStatement', |
|
|
|
|
'src': src, |
|
|
|
|
'children':[variable, init]} |
|
|
|
|
self.get_children('children'):[variable, init]} |
|
|
|
|
|
|
|
|
|
new_node = self._parse_variable_definition(new_statement, new_node) |
|
|
|
|
else: |
|
|
|
|
# If we have |
|
|
|
|
# var (a, b) = f() |
|
|
|
|
# we can split in multiple declarations, without init |
|
|
|
|
# Then we craft one expression that does not assignment |
|
|
|
|
assert tuple_vars['name'] in ['FunctionCall', 'Conditional'] |
|
|
|
|
# Then we craft one expression that does the assignment |
|
|
|
|
assert tuple_vars[self.get_key()] in ['FunctionCall', 'Conditional'] |
|
|
|
|
variables = [] |
|
|
|
|
for variable in variables_declaration: |
|
|
|
|
src = variable['src'] |
|
|
|
|
i= i+1 |
|
|
|
|
i = i+1 |
|
|
|
|
# Create a fake statement to be consistent |
|
|
|
|
new_statement = {'name':'VariableDefinitionStatement', |
|
|
|
|
new_statement = {self.get_key():'VariableDefinitionStatement', |
|
|
|
|
'src': src, |
|
|
|
|
'children':[variable]} |
|
|
|
|
self.get_children('children'):[variable]} |
|
|
|
|
variables.append(variable) |
|
|
|
|
|
|
|
|
|
new_node = self._parse_variable_definition_init_tuple(new_statement, i, new_node) |
|
|
|
@ -290,23 +471,23 @@ class FunctionSolc(Function): |
|
|
|
|
# craft of the expression doing the assignement |
|
|
|
|
for v in variables: |
|
|
|
|
identifier = { |
|
|
|
|
'name' : 'Identifier', |
|
|
|
|
self.get_key() : 'Identifier', |
|
|
|
|
'src': v['src'], |
|
|
|
|
'attributes': { |
|
|
|
|
'value': v['attributes']['name'], |
|
|
|
|
'value': v['attributes'][self.get_key()], |
|
|
|
|
'type': v['attributes']['type']} |
|
|
|
|
} |
|
|
|
|
var_identifiers.append(identifier) |
|
|
|
|
|
|
|
|
|
expression = { |
|
|
|
|
'name' : 'Assignment', |
|
|
|
|
self.get_key() : 'Assignment', |
|
|
|
|
'src':statement['src'], |
|
|
|
|
'attributes': {'operator': '=', |
|
|
|
|
'type':'tuple()'}, |
|
|
|
|
'children': |
|
|
|
|
[{'name': 'TupleExpression', |
|
|
|
|
self.get_children('children'): |
|
|
|
|
[{self.get_key(): 'TupleExpression', |
|
|
|
|
'src': statement['src'], |
|
|
|
|
'children': var_identifiers}, |
|
|
|
|
self.get_children('children'): var_identifiers}, |
|
|
|
|
tuple_vars]} |
|
|
|
|
node = new_node |
|
|
|
|
new_node = self._new_node(NodeType.EXPRESSION) |
|
|
|
@ -318,7 +499,7 @@ class FunctionSolc(Function): |
|
|
|
|
|
|
|
|
|
def _parse_variable_definition_init_tuple(self, statement, index, node): |
|
|
|
|
local_var = LocalVariableInitFromTupleSolc(statement, index) |
|
|
|
|
#local_var = LocalVariableSolc(statement['children'][0], statement['children'][1::]) |
|
|
|
|
#local_var = LocalVariableSolc(statement[self.get_children('children')][0], statement[self.get_children('children')][1::]) |
|
|
|
|
local_var.set_function(self) |
|
|
|
|
local_var.set_offset(statement['src'], self.contract.slither) |
|
|
|
|
|
|
|
|
@ -342,7 +523,7 @@ class FunctionSolc(Function): |
|
|
|
|
# Throw | EmitStatement | SimpleStatement ) ';' |
|
|
|
|
# SimpleStatement = VariableDefinition | ExpressionStatement |
|
|
|
|
|
|
|
|
|
name = statement['name'] |
|
|
|
|
name = statement[self.get_key()] |
|
|
|
|
# SimpleStatement = VariableDefinition | ExpressionStatement |
|
|
|
|
if name == 'IfStatement': |
|
|
|
|
node = self._parse_if(statement, node) |
|
|
|
@ -371,9 +552,13 @@ class FunctionSolc(Function): |
|
|
|
|
elif name == 'Return': |
|
|
|
|
return_node = self._new_node(NodeType.RETURN) |
|
|
|
|
link_nodes(node, return_node) |
|
|
|
|
if 'children' in statement and statement['children']: |
|
|
|
|
assert len(statement['children']) == 1 |
|
|
|
|
expression = statement['children'][0] |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
if statement['expression']: |
|
|
|
|
return_node.add_unparsed_expression(statement['expression']) |
|
|
|
|
else: |
|
|
|
|
if self.get_children('children') in statement and statement[self.get_children('children')]: |
|
|
|
|
assert len(statement[self.get_children('children')]) == 1 |
|
|
|
|
expression = statement[self.get_children('children')][0] |
|
|
|
|
return_node.add_unparsed_expression(expression) |
|
|
|
|
node = return_node |
|
|
|
|
elif name == 'Throw': |
|
|
|
@ -381,8 +566,11 @@ class FunctionSolc(Function): |
|
|
|
|
link_nodes(node, throw_node) |
|
|
|
|
node = throw_node |
|
|
|
|
elif name == 'EmitStatement': |
|
|
|
|
#expression = parse_expression(statement['children'][0], self) |
|
|
|
|
expression = statement['children'][0] |
|
|
|
|
#expression = parse_expression(statement[self.get_children('children')][0], self) |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
expression = statement['eventCall'] |
|
|
|
|
else: |
|
|
|
|
expression = statement[self.get_children('children')][0] |
|
|
|
|
new_node = self._new_node(NodeType.EXPRESSION) |
|
|
|
|
new_node.add_unparsed_expression(expression) |
|
|
|
|
link_nodes(node, new_node) |
|
|
|
@ -390,10 +578,13 @@ class FunctionSolc(Function): |
|
|
|
|
elif name in ['VariableDefinitionStatement', 'VariableDeclarationStatement']: |
|
|
|
|
node = self._parse_variable_definition(statement, node) |
|
|
|
|
elif name == 'ExpressionStatement': |
|
|
|
|
assert len(statement['children']) == 1 |
|
|
|
|
assert not 'attributes' in statement |
|
|
|
|
#expression = parse_expression(statement['children'][0], self) |
|
|
|
|
expression = statement['children'][0] |
|
|
|
|
#assert len(statement[self.get_children('expression')]) == 1 |
|
|
|
|
#assert not 'attributes' in statement |
|
|
|
|
#expression = parse_expression(statement[self.get_children('children')][0], self) |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
expression = statement[self.get_children('expression')] |
|
|
|
|
else: |
|
|
|
|
expression = statement[self.get_children('expression')][0] |
|
|
|
|
new_node = self._new_node(NodeType.EXPRESSION) |
|
|
|
|
new_node.add_unparsed_expression(expression) |
|
|
|
|
link_nodes(node, new_node) |
|
|
|
@ -409,20 +600,30 @@ class FunctionSolc(Function): |
|
|
|
|
Return: |
|
|
|
|
Node |
|
|
|
|
''' |
|
|
|
|
assert block['name'] == 'Block' |
|
|
|
|
assert block[self.get_key()] == 'Block' |
|
|
|
|
|
|
|
|
|
for child in block['children']: |
|
|
|
|
node = self._parse_statement(child, node) |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
statements = block['statements'] |
|
|
|
|
else: |
|
|
|
|
statements = block[self.get_children('children')] |
|
|
|
|
|
|
|
|
|
for statement in statements: |
|
|
|
|
node = self._parse_statement(statement, node) |
|
|
|
|
return node |
|
|
|
|
|
|
|
|
|
def _parse_cfg(self, cfg): |
|
|
|
|
|
|
|
|
|
assert cfg['name'] == 'Block' |
|
|
|
|
assert cfg[self.get_key()] == 'Block' |
|
|
|
|
|
|
|
|
|
node = self._new_node(NodeType.ENTRYPOINT) |
|
|
|
|
self._entry_point = node |
|
|
|
|
|
|
|
|
|
if not cfg['children']: |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
statements = cfg['statements'] |
|
|
|
|
else: |
|
|
|
|
statements = cfg[self.get_children('children')] |
|
|
|
|
|
|
|
|
|
if not statements: |
|
|
|
|
self._is_empty = True |
|
|
|
|
else: |
|
|
|
|
self._is_empty = False |
|
|
|
@ -464,7 +665,7 @@ class FunctionSolc(Function): |
|
|
|
|
end_node = self._find_end_loop(node, []) |
|
|
|
|
|
|
|
|
|
if not end_node: |
|
|
|
|
logger.error('Break in no-loop context {}'.format(node.nodeId())) |
|
|
|
|
logger.error('Break in no-loop context {}'.format(node)) |
|
|
|
|
exit(-1) |
|
|
|
|
|
|
|
|
|
for son in node.sons: |
|
|
|
@ -527,10 +728,15 @@ class FunctionSolc(Function): |
|
|
|
|
self._nodes = [n for n in self.nodes if not n in to_remove] |
|
|
|
|
# |
|
|
|
|
def _parse_params(self, params): |
|
|
|
|
assert params[self.get_key()] == 'ParameterList' |
|
|
|
|
|
|
|
|
|
assert params['name'] == 'ParameterList' |
|
|
|
|
for param in params['children']: |
|
|
|
|
assert param['name'] == 'VariableDeclaration' |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
params = params['parameters'] |
|
|
|
|
else: |
|
|
|
|
params = params[self.get_children('children')] |
|
|
|
|
|
|
|
|
|
for param in params: |
|
|
|
|
assert param[self.get_key()] == 'VariableDeclaration' |
|
|
|
|
|
|
|
|
|
local_var = LocalVariableSolc(param) |
|
|
|
|
|
|
|
|
@ -547,9 +753,15 @@ class FunctionSolc(Function): |
|
|
|
|
|
|
|
|
|
def _parse_returns(self, returns): |
|
|
|
|
|
|
|
|
|
assert returns['name'] == 'ParameterList' |
|
|
|
|
for ret in returns['children']: |
|
|
|
|
assert ret['name'] == 'VariableDeclaration' |
|
|
|
|
assert returns[self.get_key()] == 'ParameterList' |
|
|
|
|
|
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
returns = returns['parameters'] |
|
|
|
|
else: |
|
|
|
|
returns = returns[self.get_children('children')] |
|
|
|
|
|
|
|
|
|
for ret in returns: |
|
|
|
|
assert ret[self.get_key()] == 'VariableDeclaration' |
|
|
|
|
|
|
|
|
|
local_var = LocalVariableSolc(ret) |
|
|
|
|
|
|
|
|
@ -580,8 +792,11 @@ class FunctionSolc(Function): |
|
|
|
|
|
|
|
|
|
self._analyze_attributes() |
|
|
|
|
|
|
|
|
|
children = self._functionNotParsed['children'] |
|
|
|
|
|
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
params = self._functionNotParsed['parameters'] |
|
|
|
|
returns = self._functionNotParsed['returnParameters'] |
|
|
|
|
else: |
|
|
|
|
children = self._functionNotParsed[self.get_children('children')] |
|
|
|
|
params = children[0] |
|
|
|
|
returns = children[1] |
|
|
|
|
|
|
|
|
@ -596,15 +811,26 @@ class FunctionSolc(Function): |
|
|
|
|
|
|
|
|
|
self._content_was_analyzed = True |
|
|
|
|
|
|
|
|
|
children = self._functionNotParsed['children'] |
|
|
|
|
if self.is_compact_ast: |
|
|
|
|
body = self._functionNotParsed['body'] |
|
|
|
|
|
|
|
|
|
if body and body[self.get_key()] == 'Block': |
|
|
|
|
self._is_implemented = True |
|
|
|
|
self._parse_cfg(body) |
|
|
|
|
|
|
|
|
|
for modifier in self._functionNotParsed['modifiers']: |
|
|
|
|
self._parse_modifier(modifier) |
|
|
|
|
|
|
|
|
|
else: |
|
|
|
|
children = self._functionNotParsed[self.get_children('children')] |
|
|
|
|
self._is_implemented = False |
|
|
|
|
for child in children[2:]: |
|
|
|
|
if child['name'] == 'Block': |
|
|
|
|
if child[self.get_key()] == 'Block': |
|
|
|
|
self._is_implemented = True |
|
|
|
|
self._parse_cfg(child) |
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
assert child['name'] == 'ModifierInvocation' |
|
|
|
|
assert child[self.get_key()] == 'ModifierInvocation' |
|
|
|
|
|
|
|
|
|
self._parse_modifier(child) |
|
|
|
|
|
|
|
|
@ -630,13 +856,13 @@ class FunctionSolc(Function): |
|
|
|
|
break |
|
|
|
|
self._remove_alone_endif() |
|
|
|
|
|
|
|
|
|
self._analyze_read_write() |
|
|
|
|
self._analyze_calls() |
|
|
|
|
|
|
|
|
|
def convert_expression_to_slithir(self): |
|
|
|
|
for node in self.nodes: |
|
|
|
|
node.slithir_generation() |
|
|
|
|
transform_slithir_vars_to_ssa(self) |
|
|
|
|
self._analyze_read_write() |
|
|
|
|
self._analyze_calls() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def split_ternary_node(self, node, condition, true_expr, false_expr): |
|
|
|
|