@@ -78,12 +78,28 @@ TEST(analysis, push)
78
78
EXPECT_EQ (analysis.push_values [0 ], intx::uint256{0xee } << 240 );
79
79
}
80
80
81
+ TEST (analysis, jumpdest_skip)
82
+ {
83
+ // If the JUMPDEST is the first instruction in a basic block it should be just omitted
84
+ // and no new block should be created in this place.
85
+
86
+ const auto code = bytecode{} + OP_STOP + OP_JUMPDEST;
87
+ auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
88
+
89
+ EXPECT_EQ (analysis.blocks .size (), 2 );
90
+ ASSERT_EQ (analysis.instrs .size (), 4 );
91
+ EXPECT_EQ (analysis.instrs [0 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
92
+ EXPECT_EQ (analysis.instrs [1 ].fn , fake_fn_table[OP_STOP]);
93
+ EXPECT_EQ (analysis.instrs [2 ].fn , fake_fn_table[OP_JUMPDEST]);
94
+ EXPECT_EQ (analysis.instrs [3 ].fn , fake_fn_table[OP_STOP]);
95
+ }
96
+
81
97
TEST (analysis, jump1)
82
98
{
83
99
const auto code = jump (add (4 , 2 )) + OP_JUMPDEST + mstore (0 , 3 ) + ret (0 , 0x20 ) + jump (6 );
84
100
const auto analysis = analyze (fake_fn_table, rev, &code[0 ], code.size ());
85
101
86
- ASSERT_EQ (analysis.blocks .size (), 3 );
102
+ ASSERT_EQ (analysis.blocks .size (), 4 );
87
103
ASSERT_EQ (analysis.jumpdest_offsets .size (), 1 );
88
104
ASSERT_EQ (analysis.jumpdest_targets .size (), 1 );
89
105
EXPECT_EQ (analysis.jumpdest_offsets [0 ], 6 );
@@ -98,14 +114,15 @@ TEST(analysis, empty)
98
114
bytes code;
99
115
auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
100
116
101
- EXPECT_EQ (analysis.blocks .size (), 0 );
102
- EXPECT_EQ (analysis.instrs .size (), 1 );
103
- EXPECT_EQ (analysis.instrs .back ().fn , fake_fn_table[OP_STOP]);
117
+ EXPECT_EQ (analysis.blocks .size (), 1 );
118
+ EXPECT_EQ (analysis.instrs .size (), 2 );
119
+ EXPECT_EQ (analysis.instrs [0 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
120
+ EXPECT_EQ (analysis.instrs [1 ].fn , fake_fn_table[OP_STOP]);
104
121
}
105
122
106
123
TEST (analysis, only_jumpdest)
107
124
{
108
- auto code = from_hex ( " 5b " ) ;
125
+ const auto code = bytecode{OP_JUMPDEST} ;
109
126
auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
110
127
111
128
ASSERT_EQ (analysis.blocks .size (), 1 );
@@ -117,9 +134,63 @@ TEST(analysis, only_jumpdest)
117
134
118
135
TEST (analysis, jumpi_at_the_end)
119
136
{
120
- auto code = from_hex ( " 57 " ) ;
137
+ const auto code = bytecode{OP_JUMPI} ;
121
138
auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
122
139
123
- EXPECT_EQ (analysis.blocks .size (), 1 );
124
- EXPECT_EQ (analysis.instrs .back ().fn , fake_fn_table[OP_STOP]);
140
+ EXPECT_EQ (analysis.blocks .size (), 2 );
141
+ EXPECT_EQ (analysis.instrs [0 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
142
+ EXPECT_EQ (analysis.instrs [1 ].fn , fake_fn_table[OP_JUMPI]);
143
+ EXPECT_EQ (analysis.instrs [2 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
144
+ EXPECT_EQ (analysis.instrs [3 ].fn , fake_fn_table[OP_STOP]);
145
+ }
146
+
147
+ TEST (analysis, terminated_last_block)
148
+ {
149
+ // TODO: Even if the last basic block is properly terminated an additional artificial block
150
+ // is going to be created with only STOP instruction.
151
+ const auto code = ret (0 , 0 );
152
+ auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
153
+
154
+ EXPECT_EQ (analysis.blocks .size (), 2 );
155
+ ASSERT_EQ (analysis.instrs .size (), 6 );
156
+ EXPECT_EQ (analysis.instrs [0 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
157
+ EXPECT_EQ (analysis.instrs [3 ].fn , fake_fn_table[OP_RETURN]);
158
+ EXPECT_EQ (analysis.instrs [4 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
159
+ EXPECT_EQ (analysis.instrs [5 ].fn , fake_fn_table[OP_STOP]);
160
+ }
161
+
162
+ TEST (analysis, jumpdests_groups)
163
+ {
164
+ const auto code = 3 * OP_JUMPDEST + push (1 ) + 3 * OP_JUMPDEST + push (2 ) + OP_JUMPI;
165
+ auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
166
+
167
+ EXPECT_EQ (analysis.blocks .size (), 7 );
168
+ ASSERT_EQ (analysis.instrs .size (), 11 );
169
+ EXPECT_EQ (analysis.instrs [0 ].fn , fake_fn_table[OP_JUMPDEST]);
170
+ EXPECT_EQ (analysis.instrs [1 ].fn , fake_fn_table[OP_JUMPDEST]);
171
+ EXPECT_EQ (analysis.instrs [2 ].fn , fake_fn_table[OP_JUMPDEST]);
172
+ EXPECT_EQ (analysis.instrs [3 ].fn , fake_fn_table[OP_PUSH1]);
173
+ EXPECT_EQ (analysis.instrs [4 ].fn , fake_fn_table[OP_JUMPDEST]);
174
+ EXPECT_EQ (analysis.instrs [5 ].fn , fake_fn_table[OP_JUMPDEST]);
175
+ EXPECT_EQ (analysis.instrs [6 ].fn , fake_fn_table[OP_JUMPDEST]);
176
+ EXPECT_EQ (analysis.instrs [7 ].fn , fake_fn_table[OP_PUSH1]);
177
+ EXPECT_EQ (analysis.instrs [8 ].fn , fake_fn_table[OP_JUMPI]);
178
+ EXPECT_EQ (analysis.instrs [9 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
179
+ EXPECT_EQ (analysis.instrs [10 ].fn , fake_fn_table[OP_STOP]);
180
+
181
+
182
+ ASSERT_EQ (analysis.jumpdest_offsets .size (), 6 );
183
+ ASSERT_EQ (analysis.jumpdest_targets .size (), 6 );
184
+ EXPECT_EQ (analysis.jumpdest_offsets [0 ], 0 );
185
+ EXPECT_EQ (analysis.jumpdest_targets [0 ], 0 );
186
+ EXPECT_EQ (analysis.jumpdest_offsets [1 ], 1 );
187
+ EXPECT_EQ (analysis.jumpdest_targets [1 ], 1 );
188
+ EXPECT_EQ (analysis.jumpdest_offsets [2 ], 2 );
189
+ EXPECT_EQ (analysis.jumpdest_targets [2 ], 2 );
190
+ EXPECT_EQ (analysis.jumpdest_offsets [3 ], 5 );
191
+ EXPECT_EQ (analysis.jumpdest_targets [3 ], 4 );
192
+ EXPECT_EQ (analysis.jumpdest_offsets [4 ], 6 );
193
+ EXPECT_EQ (analysis.jumpdest_targets [4 ], 5 );
194
+ EXPECT_EQ (analysis.jumpdest_offsets [5 ], 7 );
195
+ EXPECT_EQ (analysis.jumpdest_targets [5 ], 6 );
125
196
}
0 commit comments