Repository: boa-dev/boa (Rust)

Issue:
Panic at break in an infinte loop, in finally block
<!--
Thank you for reporting a bug in Boa! This will make us improve the engine. But first, fill the following template so that we better understand what's happening. Feel free to add or remove sections as you feel appropriate.
-->

**Describe the bug**
In a try-catch-finally -- in the finally block, panic in a one line break statement after an infinite loop, _if there are no braces around the break statement._ 

<!-- E.g.:
The variable statement is not working as expected, it always adds 10 when assigning a number to a variable"
-->

**To Reproduce**
These JavaScripts crash with `thread 'main' panicked at 'stack was empty', boa_engine/src/vm/opcode/control_flow/finally.rs:137:59`
```js
try {
}
catch {
} finally {
 while(true) 
  break;
}
```
or 

```js
try {
}
catch {
} finally {
 for(;;)
  break;
}
```

**Expected behavior**
Should not panic. Javascript allows one-line statements after a condition to not be encompassed by braces.

<!-- E.g.:
Running this code, `a` should be set to `10` and printed, but `a` is instead set to `20`. The expected behaviour can be found in the [ECMAScript specification][spec].

[spec]: https://tc39.es/ecma262/#sec-variable-statement-runtime-semantics-evaluation
-->

**Build environment:**
• OS: Ubuntu
• Version: 20.04
• Target triple: x86_64-unknown-linux-gnu
• Rustc version: rustc 1.70.0

**Additional context**
Note that this Javascript does _not_ panic, i.e. if braces are present. It is also clearly breaking out of the infinite loop as "in finally" does get printed. 
```js
try {
}
catch {
} finally {
 while(true) {
  break;
 }
 console.log("in finally")
}
```




Discussion:
I'm sorry for not commenting on this before working on this, will make sure to do that going forward.

I think this is fixed in #3073 
#3059 Fixes this issue by completely refactoring and redesigning the execution (removed `FinallyStart/End` and many many things). I should have assigned the issue to my self to avoid the work overlap :sweat_smile: .

But it's good to have a fix for the panic until #3059 is fully complete :smile: 

> But it's good to have a fix for the panic until #3059 is fully complete 😄

Yeah, and also because we'll probably release tomorrow, so #3059 will probably arrive to our users until 0.18.




Patch:
diff --git a/boa_engine/src/vm/opcode/control_flow/finally.rs b/boa_engine/src/vm/opcode/control_flow/finally.rs
index f3271ea124b..9a41e2dc163 100644
--- a/boa_engine/src/vm/opcode/control_flow/finally.rs
+++ b/boa_engine/src/vm/opcode/control_flow/finally.rs
@@ -119,7 +119,7 @@ impl Operation for FinallyEnd {
                 let env_truncation_len = context.vm.environments.len().saturating_sub(envs_to_pop);
                 context.vm.environments.truncate(env_truncation_len);
             }
-            Some(record) if !record.is_throw_with_target() => {
+            Some(record) if record.is_throw() && !record.is_throw_with_target() => {
                 let current_stack = context
                     .vm
                     .frame_mut()


Test patch:
diff --git a/boa_engine/src/tests/control_flow/mod.rs b/boa_engine/src/tests/control_flow/mod.rs
index 8078bf49bf1..eabfae5c9c8 100644
--- a/boa_engine/src/tests/control_flow/mod.rs
+++ b/boa_engine/src/tests/control_flow/mod.rs
@@ -194,6 +194,24 @@ fn catch_binding_finally() {
     )]);
 }
 
+#[test]
+fn finally_with_loop_break() {
+    run_test_actions([TestAction::assert_eq(
+        indoc! {r#"
+            try {
+              30;
+            }
+            catch {
+            } finally {
+              while(true) {
+                break;
+              }
+            }
+        "#},
+        30,
+    )]);
+}
+
 #[test]
 fn single_case_switch() {
     run_test_actions([TestAction::assert_eq(