1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-10 11:57:35 +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

@ -899,24 +899,30 @@ Value Object::invoke(const StringOrSymbol& property_name, Optional<MarkedValueLi
Value Object::call_native_property_getter(Object* this_object, Value property) const
{
ASSERT(property.is_native_property());
auto& vm = this->vm();
CallFrame call_frame;
call_frame.is_strict_mode = vm().in_strict_mode();
call_frame.is_strict_mode = vm.in_strict_mode();
call_frame.this_value = this_object;
vm().push_call_frame(call_frame);
auto result = property.as_native_property().get(vm(), global_object());
vm().pop_call_frame();
vm.push_call_frame(call_frame, global_object());
if (vm.exception())
return {};
auto result = property.as_native_property().get(vm, global_object());
vm.pop_call_frame();
return result;
}
void Object::call_native_property_setter(Object* this_object, Value property, Value value) const
{
ASSERT(property.is_native_property());
auto& vm = this->vm();
CallFrame call_frame;
call_frame.is_strict_mode = vm().in_strict_mode();
call_frame.is_strict_mode = vm.in_strict_mode();
call_frame.this_value = this_object;
vm().push_call_frame(call_frame);
property.as_native_property().set(vm(), global_object(), value);
vm().pop_call_frame();
vm.push_call_frame(call_frame, global_object());
if (vm.exception())
return;
property.as_native_property().set(vm, global_object(), value);
vm.pop_call_frame();
}
}