MCPcopy Create free account
hub / github.com/diem/move / check_no_loop_splits

Function check_no_loop_splits

language/move-bytecode-verifier/src/control_flow.rs:187–217  ·  view source on GitHub ↗
(context: &ControlFlowVerifier, labels: &[Label])

Source from the content-addressed store, hash-verified

185}
186
187fn check_no_loop_splits(context: &ControlFlowVerifier, labels: &[Label]) -> PartialVMResult<()> {
188 let is_break = |loop_stack: &Vec<(CodeOffset, CodeOffset)>, jump_target: CodeOffset| -> bool {
189 match loop_stack.last() {
190 None => false,
191 Some((_cur_loop_head, last_continue)) => jump_target > *last_continue,
192 }
193 };
194 let loop_depth = count_loop_depth(labels);
195 check_code(context, labels, |loop_stack, i, instr| {
196 match instr {
197 // Forward jump/"break"
198 Bytecode::Branch(j) | Bytecode::BrTrue(j) | Bytecode::BrFalse(j)
199 if *j > i && !is_break(loop_stack, *j) =>
200 {
201 let j = *j;
202 let before_depth = loop_depth[i as usize];
203 let after_depth = match &labels[j as usize] {
204 Label::Loop { .. } => loop_depth[j as usize] - 1,
205 Label::Code => loop_depth[j as usize],
206 };
207 if before_depth != after_depth {
208 // Invalid forward jump. Entered the middle of a loop
209 Err(context.error(StatusCode::INVALID_LOOP_SPLIT, i))
210 } else {
211 Ok(())
212 }
213 }
214 _ => Ok(()),
215 }
216 })
217}
218
219// Only called after continues are verified, so we can assume that loops are well nested
220fn count_loop_depth(labels: &[Label]) -> Vec<usize> {

Callers 1

check_jumpsFunction · 0.85

Calls 3

count_loop_depthFunction · 0.85
check_codeFunction · 0.85
errorMethod · 0.45

Tested by

no test coverage detected