1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 14:28:12 +00:00

LibJS: Throw RuntimeError when reaching the end of the stack

This prevents stack overflows when calling infinite/deep recursive
functions, e.g.:

    const f = () => f(); f();
    JSON.stringify({}, () => ({ foo: "bar" }));
    new Proxy({}, { get: (_, __, p) => p.foo }).foo;

The VM caches a StackInfo object to not slow down function calls
considerably. VM::push_call_frame() will throw an exception if
necessary (plain Error with "RuntimeError" as its .name).
This commit is contained in:
Linus Groh 2020-11-08 12:54:52 +00:00 committed by Andreas Kling
parent 9c3ead8f91
commit a02b9983f9
5 changed files with 58 additions and 18 deletions

View file

@ -196,8 +196,10 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
{
CallFrame call_frame;
call_frame.is_strict_mode = function.is_strict_mode();
push_call_frame(call_frame);
push_call_frame(call_frame, function.global_object());
if (exception())
return {};
ArmedScopeGuard call_frame_popper = [&] {
pop_call_frame();
};
@ -323,8 +325,12 @@ Value VM::call_internal(Function& function, Value this_value, Optional<MarkedVal
ASSERT(call_frame.environment->this_binding_status() == LexicalEnvironment::ThisBindingStatus::Uninitialized);
call_frame.environment->bind_this_value(function.global_object(), call_frame.this_value);
if (exception())
return {};
push_call_frame(call_frame);
push_call_frame(call_frame, function.global_object());
if (exception())
return {};
auto result = function.call();
pop_call_frame();
return result;