Crate sandkiste_lua
source ·Expand description
Using the Lua programming language with the sandkiste
sandboxing API
Features
This crate allows executing Lua code in a sandbox where memory usage and the number of executed Lua instructions can be limited.
It uses the sandkiste
API, which is an interface that can also be used
for sandboxing other scripting languages than Lua.
It is possible to call Lua functions from Rust or to call Rust closures from Lua. However, execution time in Rust (or waiting for I/O) is not counting towards resource limits.
Different Lua versions
Upon building, either Lua version 5.3 or 5.4 must be selected by specifying
one of the features Lua5_3
or Lua5_4
. Currently, it is not possible to
build this crate with support for both Lua versions at the same time.
To allow lifting this restriction in future, items are contained in a
module reflecting the Lua version being used (module v5_3
or v5_4
).
Example use
use sandkiste::prelude::*;
#[cfg(feature = "Lua5_3")]
use sandkiste_lua::v5_3::{LuaMachine, LuaDatum};
#[cfg(feature = "Lua5_4")]
use sandkiste_lua::v5_4::{LuaMachine, LuaDatum};
use std::cell::RefCell;
let output_cell = RefCell::new(String::new());
let machine = LuaMachine::new();
machine.load_stdlib().expect("could not load Lua standard lib");
machine
.compile(
Some("init".to_string()),
"-- require 'some_library'",
)
.expect("could not compile initialization code")
.call([])
.expect("could not run initialization code");
// remove certain functions from Lua's standard library:
machine.seal().expect("could not seal sandbox");
let my_print = machine
.callback_1arg(|s| {
let s = s.try_as_str()?;
let mut output = output_cell.borrow_mut();
output.push_str(s);
Ok([])
})
.expect("could not create closure for myprint");
machine
.compile(
Some("set_myprint".to_string()),
"myprint = ...",
)
.expect("could not compile code to set myprint")
.call([my_print])
.expect("could not run code to set myprint");
let main = machine
.compile(
Some("main".to_string()),
"\
local args = {...}\n\
myprint('Hello ')\n\
myprint(args[1])\n\
myprint('!')\n\
"
)
.expect("could not compile main Lua function");
let name: LuaDatum = "Rust".into();
main.call([name]).expect("runtime error in main Lua function");
// dropping these lets us move out of `output_cell`, which is still
// borrowed by the closure that has been moved to the machine:
drop(main);
drop(machine);
let output = output_cell.into_inner();
assert_eq!(output, "Hello Rust!");
Modules
- Foreign function interface for C part of implementation (including C bindings for Lua)
- Support for Lua 5.3