diff --git a/boa/src/bytecompiler.rs b/boa/src/bytecompiler.rs index 7a88a6a9db..7d4ad25d78 100644 --- a/boa/src/bytecompiler.rs +++ b/boa/src/bytecompiler.rs @@ -1471,19 +1471,26 @@ impl<'b> ByteCompiler<'b> { self.emit(Opcode::FinallySetJump, &[u32::MAX]); } let label = self.jump(); - if node.label().is_none() { - self.jump_info - .last_mut() - .expect("no jump information found") - .breaks - .push(label); - } else { + if let Some(label_name) = node.label() { + let mut found = false; for info in self.jump_info.iter_mut().rev() { - if info.label == node.label() { + if info.label == Some(label_name) { info.breaks.push(label); + found = true; break; } } + assert!( + found, + "Undefined label '{}'", + self.interner().resolve_expect(label_name) + ); + } else { + self.jump_info + .last_mut() + .expect("no jump information found") + .breaks + .push(label); } } Node::Block(block) => { diff --git a/boa/src/tests.rs b/boa/src/tests.rs index 10ad9d0a4f..1d8176012a 100644 --- a/boa/src/tests.rs +++ b/boa/src/tests.rs @@ -430,6 +430,18 @@ fn for_loop_iteration_variable_does_not_leak() { assert_eq!(&exec(inner_scope), "\"i is not defined\""); } +#[test] +#[should_panic] +fn test_invalid_break_target() { + let src = r#" + while (false) { + break nonexistent; + } + "#; + + let _ = &exec(src); +} + #[test] fn unary_pre() { let unary_inc = r#"