summaryrefslogtreecommitdiff
path: root/src/thread.rs
diff options
context:
space:
mode:
authorAlex Orlenko <zxteam@protonmail.com>2022-03-28 23:42:35 +0100
committerAlex Orlenko <zxteam@protonmail.com>2022-03-28 23:42:35 +0100
commit87c10ca93dec7189330bdb0aad2daed5a1cd78fe (patch)
tree48d9c97dfcf7127629d142399bb67775a3a538cd /src/thread.rs
parentf75b7b7879e1c3c9d12b02a42903d04eb26e8635 (diff)
downloadmlua-87c10ca93dec7189330bdb0aad2daed5a1cd78fe.zip
Sandboxing support
Diffstat (limited to 'src/thread.rs')
-rw-r--r--src/thread.rs60
1 files changed, 59 insertions, 1 deletions
diff --git a/src/thread.rs b/src/thread.rs
index 0be0664..d710c92 100644
--- a/src/thread.rs
+++ b/src/thread.rs
@@ -214,6 +214,13 @@ impl<'lua> Thread<'lua> {
lua.push_ref(&func.0);
ffi::lua_xmove(lua.state, thread_state, 1);
+ #[cfg(feature = "luau")]
+ {
+ // Inherit `LUA_GLOBALSINDEX` from the caller
+ ffi::lua_xpush(lua.state, thread_state, ffi::LUA_GLOBALSINDEX);
+ ffi::lua_replace(thread_state, ffi::LUA_GLOBALSINDEX);
+ }
+
Ok(())
}
}
@@ -278,6 +285,53 @@ impl<'lua> Thread<'lua> {
recycle: false,
}
}
+
+ /// Enables sandbox mode on this thread.
+ ///
+ /// Under the hood replaces the global environment table with a new table,
+ /// that performs writes locally and proxies reads to caller's global environment.
+ ///
+ /// This mode ideally should be used together with the global sandbox mode [`Lua::sandbox()`].
+ ///
+ /// Please note that Luau links environment table with chunk when loading it into Lua state.
+ /// Therefore you need to load chunks into a thread to link with the thread environment.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use mlua::{Lua, Result};
+ /// # fn main() -> Result<()> {
+ /// let lua = Lua::new();
+ /// let thread = lua.create_thread(lua.create_function(|lua2, ()| {
+ /// lua2.load("var = 123").exec()?;
+ /// assert_eq!(lua2.globals().get::<_, u32>("var")?, 123);
+ /// Ok(())
+ /// })?)?;
+ /// thread.sandbox()?;
+ /// thread.resume(())?;
+ ///
+ /// // The global environment should be unchanged
+ /// assert_eq!(lua.globals().get::<_, Option<u32>>("var")?, None);
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// Requires `feature = "luau"`
+ #[cfg(any(feature = "luau", doc))]
+ #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
+ #[doc(hidden)]
+ pub fn sandbox(&self) -> Result<()> {
+ let lua = self.0.lua;
+ unsafe {
+ let thread = lua.ref_thread_exec(|t| ffi::lua_tothread(t, self.0.index));
+ check_stack(thread, 1)?;
+ check_stack(lua.state, 3)?;
+ // Inherit `LUA_GLOBALSINDEX` from the caller
+ ffi::lua_xpush(lua.state, thread, ffi::LUA_GLOBALSINDEX);
+ ffi::lua_replace(thread, ffi::LUA_GLOBALSINDEX);
+ protect_lua!(lua.state, 0, 0, |_| ffi::luaL_sandboxthread(thread))
+ }
+ }
}
impl<'lua> PartialEq for Thread<'lua> {
@@ -295,7 +349,11 @@ impl<'lua, R> AsyncThread<'lua, R> {
}
#[cfg(feature = "async")]
-#[cfg(any(feature = "lua54", all(feature = "luajit", feature = "vendored")))]
+#[cfg(any(
+ feature = "lua54",
+ all(feature = "luajit", feature = "vendored"),
+ feature = "luau",
+))]
impl<'lua, R> Drop for AsyncThread<'lua, R> {
fn drop(&mut self) {
if self.recycle {