This repository has been archived on 2025-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
rhaj/_archive/rhai_engine/rhaibook/safety/max-call-stack.md
2025-04-04 08:28:07 +02:00

89 lines
2.6 KiB
Markdown

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.
```rust
// This is a function that, when called, recurses forever.
fn recurse_forever() {
recurse_forever();
}
```
```admonish info.side "Main stack size"
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).
```rust
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)
```
```admonish info.small "Additional considerations"
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);
~~~
```
```admonish tip.small "Tip: Getting around the stack size limit"
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.
```