mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:57:45 +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:
parent
9c3ead8f91
commit
a02b9983f9
5 changed files with 58 additions and 18 deletions
|
@ -32,6 +32,7 @@
|
|||
#include <AK/StackInfo.h>
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
#include <LibJS/Runtime/CommonPropertyNames.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/ErrorTypes.h>
|
||||
#include <LibJS/Runtime/Exception.h>
|
||||
#include <LibJS/Runtime/MarkedValueList.h>
|
||||
|
@ -115,9 +116,15 @@ public:
|
|||
return *m_single_ascii_character_strings[character];
|
||||
}
|
||||
|
||||
void push_call_frame(CallFrame& call_frame)
|
||||
void push_call_frame(CallFrame& call_frame, GlobalObject& global_object)
|
||||
{
|
||||
m_call_stack.append(&call_frame);
|
||||
ASSERT(!exception());
|
||||
// Ensure we got some stack space left, so the next function call doesn't kill us.
|
||||
// This value is merely a guess and might need tweaking at a later point.
|
||||
if (m_stack_info.size_free() < 16 * KiB)
|
||||
throw_exception<Error>(global_object, "RuntimeError", "Call stack size limit exceeded");
|
||||
else
|
||||
m_call_stack.append(&call_frame);
|
||||
}
|
||||
|
||||
void pop_call_frame() { m_call_stack.take_last(); }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue