summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS
diff options
context:
space:
mode:
authorLuke Wilde <lukew@serenityos.org>2022-03-14 02:20:50 +0000
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2022-03-14 21:15:27 +0330
commitada8880f581bcc9ebda694ea28cead2e73937b0e (patch)
tree5055f669143dd1a00776058d40632972747874ff /Userland/Libraries/LibJS
parent0356239f3e4d31a0b19e8582403edd896100db69 (diff)
downloadserenity-ada8880f581bcc9ebda694ea28cead2e73937b0e.zip
LibJS: Leave unwind context if it has no finalizer when using handler
For example, a try/catch block with no finally. The try block and catch block do not need to unwind to a finally block, so the unwind context is no longer needed when we jump to the catch block. If we threw an exception in a catch block of a try/catch, there will be no handler or finalizer and the unit would continue on as if nothing happened. This would subsequently crash with the `m_saved_exception.is_null()` assertion failure when we next call a non-native function.
Diffstat (limited to 'Userland/Libraries/LibJS')
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Interpreter.cpp8
1 files changed, 8 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp
index f2c104091c..6d8f7262d0 100644
--- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp
+++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp
@@ -92,6 +92,11 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
if (unwind_context.handler) {
block = unwind_context.handler;
unwind_context.handler = nullptr;
+
+ // If there's no finalizer, there's nowhere for the handler block to unwind to, so the unwind context is no longer needed.
+ if (!unwind_context.finalizer)
+ m_unwind_contexts.take_last();
+
accumulator() = exception_value;
m_saved_exception = {};
will_jump = true;
@@ -103,6 +108,9 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
will_jump = true;
break;
}
+ // An unwind context with no handler or finalizer? We have nowhere to jump, and continuing on will make us crash on the next `Call` to a non-native function if there's an exception! So let's crash here instead.
+ // If you run into this, you probably forgot to remove the current unwind_context somewhere.
+ VERIFY_NOT_REACHED();
}
if (m_pending_jump.has_value()) {
block = m_pending_jump.release_value();