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-map-size.md
2025-04-04 08:28:07 +02:00

2.5 KiB

Maximum Size of Object Maps

{{#include ../links.md}}

Rhai by default does not limit how large (i.e. the number of properties) an [object map] can be.

This can be changed via Engine::set_max_map_size, with zero being unlimited (the default).

A script attempting to create an [object map] literal with more properties than the maximum will terminate with a parse error.

Any script operation that produces an [object map] with more properties than the maximum also terminates the script with an error.

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_map_size(500);       // allow object maps with only up to 500 properties

engine.set_max_map_size(0);         // allow unlimited object maps

Be conservative when setting a maximum limit and always consider the fact that a registered function
may grow an [object map]'s size without Rhai noticing until the very end.

For instance, the built-in `+` operator for [object maps] concatenates two [object maps] together to
form one larger [object map]; if both [object maps] are _slightly_ below the maximum size limit, the
resultant [object map] may be almost _twice_ the maximum size.

As a malicious script may create a deeply-nested [object map] which consumes huge amounts of memory
while each individual [object map] still stays under the maximum size limit, Rhai also _recursively_
adds up the sizes of all [strings], [arrays] and [object maps] contained within each [object map] to
make sure that the _aggregate_ sizes of none of these data structures exceed their respective
maximum size limits (if any).

```rust
// Small, innocent object map...
let small_map: #{ x: 42 };          // 1-deep... 1 item, 1 object map

// ... becomes huge when multiplied!
small_map.y = small_map;            // 2-deep... 2 items, 2 object maps
small_map.y = small_map;            // 3-deep... 4 items, 4 object maps
small_map.y = small_map;            // 4-deep... 8 items, 8 object maps
small_map.y = small_map;            // 5-deep... 16 items, 16 object maps
          :
          :
small_map.y = small_map;            // <- Rhai raises an error somewhere here
small_map.y = small_map;            //    when the TOTAL number of items in
small_map.y = small_map;            //    the entire array tree exceeds limit

// Or this abomination...
let map = #{ x: 42 };

loop {
    map.x = map;    // <- only 1 item, but infinite number of object maps
}
```