handle break/continue

pull/2099/head
alpharush 1 year ago
parent 16140f29c8
commit 9c4bc505d3
  1. 65
      slither/vyper_parsing/declarations/function.py
  2. 40
      tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt
  3. 40
      tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for3_get_D__0.txt
  4. 164
      tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_break_continue_f__0.txt
  5. 40
      tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt

@ -229,7 +229,12 @@ class FunctionVyper:
curr_node = entry_node
for expr in cfg:
def parse_statement(curr_node, expr):
def parse_statement(
curr_node: NodeVyper,
expr: ASTNode,
continue_destination=None,
break_destination=None,
) -> NodeVyper:
if isinstance(expr, AnnAssign):
local_var = LocalVariable()
local_var.set_function(self._function)
@ -266,6 +271,8 @@ class FunctionVyper:
elif isinstance(expr, For):
node_startLoop = self._new_node(NodeType.STARTLOOP, expr.src, scope)
node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope)
link_underlying_nodes(curr_node, node_startLoop)
local_var = LocalVariable()
@ -371,18 +378,10 @@ class FunctionVyper:
else:
raise NotImplementedError
# After creating condition node, we link it declaration of the loop variable
link_underlying_nodes(counter_node, node_condition)
# We update the index variable or range variable in the loop body
expr.body.insert(0, loop_var)
body_node = None
new_node = node_condition
for stmt in expr.body:
body_node = parse_statement(new_node, stmt)
new_node = body_node
node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope)
# Create an expression for the loop increment (counter_var += 1)
loop_increment = AugAssign(
"-1:-1:-1",
-1,
@ -394,6 +393,25 @@ class FunctionVyper:
node_increment.add_unparsed_expression(loop_increment)
link_underlying_nodes(node_increment, node_condition)
prev_continue_destination = continue_destination
prev_break_destination = break_destination
continue_destination = node_increment
break_destination = node_endLoop
# We assign the index variable or range variable in the loop body on each iteration
expr.body.insert(0, loop_var)
body_node = None
new_node = node_condition
for stmt in expr.body:
body_node = parse_statement(
new_node, stmt, continue_destination, break_destination
)
new_node = body_node
# Reset to previous jump destinations for nested loops
continue_destination = prev_continue_destination
break_destination = prev_break_destination
if body_node is not None:
link_underlying_nodes(body_node, node_increment)
@ -402,9 +420,15 @@ class FunctionVyper:
curr_node = node_endLoop
elif isinstance(expr, Continue):
pass
new_node = self._new_node(NodeType.CONTINUE, expr.src, scope)
link_underlying_nodes(curr_node, new_node)
link_underlying_nodes(new_node, continue_destination)
elif isinstance(expr, Break):
pass
new_node = self._new_node(NodeType.BREAK, expr.src, scope)
link_underlying_nodes(curr_node, new_node)
link_underlying_nodes(new_node, break_destination)
elif isinstance(expr, Return):
new_node = self._new_node(NodeType.RETURN, expr.src, scope)
if expr.value is not None:
@ -436,19 +460,22 @@ class FunctionVyper:
true_node = None
new_node = condition_node
for stmt in expr.body:
true_node = parse_statement(new_node, stmt)
true_node = parse_statement(
new_node, stmt, continue_destination, break_destination
)
new_node = true_node
# link_underlying_nodes(condition_node, true_node)
link_underlying_nodes(true_node, endIf_node)
false_node = None
new_node = condition_node
for stmt in expr.orelse:
false_node = parse_statement(new_node, stmt)
false_node = parse_statement(
new_node, stmt, continue_destination, break_destination
)
new_node = false_node
if false_node is not None:
# link_underlying_nodes(condition_node, false_node)
link_underlying_nodes(false_node, endIf_node)
else:
@ -481,13 +508,11 @@ class FunctionVyper:
local_var = LocalVariable()
local_var.set_function(self._function)
local_var.set_offset(param.src, self._function.compilation_unit)
print("add_param", param)
local_var_parser = LocalVariableVyper(local_var, param)
if initialized:
local_var.initialized = True
# see https://solidity.readthedocs.io/en/v0.4.24/types.html?highlight=storage%20location#data-location
if local_var.location == "default":
local_var.set_location("memory")
@ -496,7 +521,6 @@ class FunctionVyper:
def _parse_params(self, params: Arguments):
print(params)
self._function.parameters_src().set_offset(params.src, self._function.compilation_unit)
if params.defaults:
self._function._default_args_as_expressions = params.defaults
@ -506,7 +530,6 @@ class FunctionVyper:
def _parse_returns(self, returns: Union[Name, Tuple, Subscript]):
print(returns)
self._function.returns_src().set_offset(returns.src, self._function.compilation_unit)
# Only the type of the arg is given, not a name. We create an an `Arg` with an empty name
# so that the function has the correct return type in its signature but doesn't clash with

@ -12,16 +12,18 @@ _strategies(address[3]) = ['strategies(address[3])']"];
1->2;
2[label="Node Type: BEGIN_LOOP 2
"];
2->3;
3[label="Node Type: NEW VARIABLE 3
2->4;
3[label="Node Type: END_LOOP 3
"];
4[label="Node Type: NEW VARIABLE 4
EXPRESSION:
counter_var = 0
IRs:
counter_var(uint256) := 0(uint256)"];
3->4;
4[label="Node Type: IF_LOOP 4
4->5;
5[label="Node Type: IF_LOOP 5
EXPRESSION:
counter_var <= 10
@ -29,17 +31,25 @@ counter_var <= 10
IRs:
TMP_0(bool) = counter_var <= 10
CONDITION TMP_0"];
4->5[label="True"];
4->7[label="False"];
5[label="Node Type: NEW VARIABLE 5
5->7[label="True"];
5->3[label="False"];
6[label="Node Type: EXPRESSION 6
EXPRESSION:
counter_var += 1
IRs:
counter_var(uint256) = counter_var (c)+ 1"];
6->5;
7[label="Node Type: NEW VARIABLE 7
EXPRESSION:
i = counter_var
IRs:
i(uint256) := counter_var(uint256)"];
5->6;
6[label="Node Type: NEW VARIABLE 6
7->8;
8[label="Node Type: NEW VARIABLE 8
EXPRESSION:
max_withdraw = IStrategy(_strategies[i]).maxWithdraw(self)
@ -49,15 +59,5 @@ REF_0(address) -> _strategies[i]
TMP_1 = CONVERT REF_0 to IStrategy
TMP_2(uint256) = HIGH_LEVEL_CALL, dest:TMP_1(IStrategy), function:maxWithdraw, arguments:['self']
max_withdraw(uint256) := TMP_2(uint256)"];
6->8;
7[label="Node Type: END_LOOP 7
"];
8[label="Node Type: EXPRESSION 8
EXPRESSION:
counter_var += 1
IRs:
counter_var(uint256) = counter_var (c)+ 1"];
8->4;
8->6;
}

@ -12,16 +12,18 @@ S(uint256) := 0(uint256)"];
1->2;
2[label="Node Type: BEGIN_LOOP 2
"];
2->3;
3[label="Node Type: NEW VARIABLE 3
2->4;
3[label="Node Type: END_LOOP 3
"];
4[label="Node Type: NEW VARIABLE 4
EXPRESSION:
counter_var = 0
IRs:
counter_var(uint256) := 0(uint256)"];
3->4;
4[label="Node Type: IF_LOOP 4
4->5;
5[label="Node Type: IF_LOOP 5
EXPRESSION:
counter_var <= len()(_xp)
@ -30,33 +32,31 @@ IRs:
TMP_0(uint256) = SOLIDITY_CALL len()(_xp)
TMP_1(bool) = counter_var <= TMP_0
CONDITION TMP_1"];
4->5[label="True"];
4->7[label="False"];
5[label="Node Type: NEW VARIABLE 5
5->7[label="True"];
5->3[label="False"];
6[label="Node Type: EXPRESSION 6
EXPRESSION:
x = _xp[counter_var]
counter_var += 1
IRs:
REF_0(uint256) -> _xp[counter_var]
x(uint256) := REF_0(uint256)"];
5->6;
6[label="Node Type: EXPRESSION 6
counter_var(uint256) = counter_var (c)+ 1"];
6->5;
7[label="Node Type: NEW VARIABLE 7
EXPRESSION:
S += x
x = _xp[counter_var]
IRs:
S(uint256) = S (c)+ x"];
6->8;
7[label="Node Type: END_LOOP 7
"];
REF_0(uint256) -> _xp[counter_var]
x(uint256) := REF_0(uint256)"];
7->8;
8[label="Node Type: EXPRESSION 8
EXPRESSION:
counter_var += 1
S += x
IRs:
counter_var(uint256) = counter_var (c)+ 1"];
8->4;
S(uint256) = S (c)+ x"];
8->6;
}

@ -0,0 +1,164 @@
digraph{
0[label="Node Type: ENTRY_POINT 0
"];
0->1;
1[label="Node Type: BEGIN_LOOP 1
"];
1->3;
2[label="Node Type: END_LOOP 2
"];
3[label="Node Type: NEW VARIABLE 3
EXPRESSION:
counter_var = 0
IRs:
counter_var(uint256) := 0(uint256)"];
3->4;
4[label="Node Type: IF_LOOP 4
EXPRESSION:
counter_var <= 100
IRs:
TMP_0(bool) = counter_var <= 100
CONDITION TMP_0"];
4->6[label="True"];
4->2[label="False"];
5[label="Node Type: EXPRESSION 5
EXPRESSION:
counter_var += 1
IRs:
counter_var(uint256) = counter_var (c)+ 1"];
5->4;
6[label="Node Type: NEW VARIABLE 6
EXPRESSION:
i = counter_var
IRs:
i(uint256) := counter_var(uint256)"];
6->7;
7[label="Node Type: IF 7
EXPRESSION:
i > 100
IRs:
TMP_1(bool) = i > 100
CONDITION TMP_1"];
7->9[label="True"];
7->8[label="False"];
8[label="Node Type: END_IF 8
"];
8->10;
9[label="Node Type: BREAK 9
"];
9->2;
10[label="Node Type: IF 10
EXPRESSION:
i < 3
IRs:
TMP_2(bool) = i < 3
CONDITION TMP_2"];
10->12[label="True"];
10->11[label="False"];
11[label="Node Type: END_IF 11
"];
11->13;
12[label="Node Type: CONTINUE 12
"];
12->5;
13[label="Node Type: NEW VARIABLE 13
EXPRESSION:
x = 10
IRs:
x(uint256) := 10(uint256)"];
13->14;
14[label="Node Type: BEGIN_LOOP 14
"];
14->16;
15[label="Node Type: END_LOOP 15
"];
15->5;
16[label="Node Type: NEW VARIABLE 16
EXPRESSION:
counter_var_scope_0 = 0
IRs:
counter_var_scope_0(uint256) := 0(uint256)"];
16->17;
17[label="Node Type: IF_LOOP 17
EXPRESSION:
counter_var <= 10
IRs:
TMP_3(bool) = counter_var <= 10
CONDITION TMP_3"];
17->19[label="True"];
17->15[label="False"];
18[label="Node Type: EXPRESSION 18
EXPRESSION:
counter_var += 1
IRs:
counter_var(uint256) = counter_var (c)+ 1"];
18->17;
19[label="Node Type: NEW VARIABLE 19
EXPRESSION:
j = counter_var
IRs:
j(uint256) := counter_var(uint256)"];
19->20;
20[label="Node Type: IF 20
EXPRESSION:
j > 10
IRs:
TMP_4(bool) = j > 10
CONDITION TMP_4"];
20->22[label="True"];
20->21[label="False"];
21[label="Node Type: END_IF 21
"];
21->23;
22[label="Node Type: CONTINUE 22
"];
22->18;
23[label="Node Type: IF 23
EXPRESSION:
j < 3
IRs:
TMP_5(bool) = j < 3
CONDITION TMP_5"];
23->25[label="True"];
23->24[label="False"];
24[label="Node Type: END_IF 24
"];
24->26;
25[label="Node Type: BREAK 25
"];
25->15;
26[label="Node Type: EXPRESSION 26
EXPRESSION:
x -= 1
IRs:
x(uint256) = x (c)- 1"];
26->18;
}

@ -4,16 +4,18 @@ digraph{
0->1;
1[label="Node Type: BEGIN_LOOP 1
"];
1->2;
2[label="Node Type: NEW VARIABLE 2
1->3;
2[label="Node Type: END_LOOP 2
"];
3[label="Node Type: NEW VARIABLE 3
EXPRESSION:
counter_var = 0
IRs:
counter_var(uint256) := 0(uint256)"];
2->3;
3[label="Node Type: IF_LOOP 3
3->4;
4[label="Node Type: IF_LOOP 4
EXPRESSION:
counter_var <= len()(self.strategies)
@ -22,9 +24,17 @@ IRs:
TMP_0(uint256) = SOLIDITY_CALL len()(strategies)
TMP_1(bool) = counter_var <= TMP_0
CONDITION TMP_1"];
3->4[label="True"];
3->6[label="False"];
4[label="Node Type: NEW VARIABLE 4
4->6[label="True"];
4->2[label="False"];
5[label="Node Type: EXPRESSION 5
EXPRESSION:
counter_var += 1
IRs:
counter_var(uint256) = counter_var (c)+ 1"];
5->4;
6[label="Node Type: NEW VARIABLE 6
EXPRESSION:
strategy = strategies[counter_var]
@ -32,8 +42,8 @@ strategy = strategies[counter_var]
IRs:
REF_0(address) -> strategies[counter_var]
strategy(address) := REF_0(address)"];
4->5;
5[label="Node Type: NEW VARIABLE 5
6->7;
7[label="Node Type: NEW VARIABLE 7
EXPRESSION:
z = IStrategy(strategy).asset()
@ -42,15 +52,5 @@ IRs:
TMP_2 = CONVERT strategy to IStrategy
TMP_3(address) = HIGH_LEVEL_CALL, dest:TMP_2(IStrategy), function:asset, arguments:[]
z(address) := TMP_3(address)"];
5->7;
6[label="Node Type: END_LOOP 6
"];
7[label="Node Type: EXPRESSION 7
EXPRESSION:
counter_var += 1
IRs:
counter_var(uint256) = counter_var (c)+ 1"];
7->3;
7->5;
}

Loading…
Cancel
Save