2.6 KiB
2.6 KiB
Maximum Call Stack Depth
{{#include ../links.md}}
In Rhai, it is trivial for a function call to perform infinite recursion (or a very deeply-nested recursion) such that all stack space is exhausted.
// This is a function that, when called, recurses forever.
fn recurse_forever() {
recurse_forever();
}
The main stack-size of a program is _not_ determined by Rust but is platform-dependent.
See [this on-line Rust docs](https://doc.rust-lang.org/std/thread/#stack-size) for more details.
Because of its intended embedded usage, Rhai, by default, limits function calls to a maximum depth of 64 levels (8 levels in debug build) in order to fit into most platforms' default stack sizes.
This limit may be changed via the [Engine::set_max_call_levels
][options] method.
A script exceeding the maximum call stack depth will terminate with an error result.
This check can be disabled via the [unchecked
] feature for higher performance (but higher risks as well).
let mut engine = Engine::new();
engine.set_max_call_levels(10); // allow only up to 10 levels of function calls
engine.set_max_call_levels(0); // allow no function calls at all (max depth = zero)
When setting this limit, care must be also be taken to the evaluation depth of each _statement_
within a function.
It is entirely possible for a malicious script to embed a recursive call deep inside a nested
expression or statements block (see [maximum statement depth]).
~~~rust
fn bad_function(n) {
// Bail out long before reaching the limit
if n > 10 {
return;
}
// Nest many, many levels deep...
if check_1() {
if check_2() {
if check_3() {
if check_4() {
:
if check_n() {
bad_function(n+1); // <- recursive call!
}
:
}
}
}
}
}
// The function call below may still overflow the stack!
bad_function(0);
~~~
While the stack size of a program's _main_ thread is platform-specific, Rust defaults to a stack
size of 2MB for spawned threads.
This default can further be changed such that a spawned thread has as large a stack as needed.
See [the on-line Rust docs](https://doc.rust-lang.org/std/thread/#stack-size) for more details.
Therefore, in order to relax the stack size limit for scripts, run the [`Engine`] in a separate
spawned thread with a larger stack.