diff options
author | Alex Orlenko <zxteam@protonmail.com> | 2022-03-28 23:42:35 +0100 |
---|---|---|
committer | Alex Orlenko <zxteam@protonmail.com> | 2022-03-28 23:42:35 +0100 |
commit | 87c10ca93dec7189330bdb0aad2daed5a1cd78fe (patch) | |
tree | 48d9c97dfcf7127629d142399bb67775a3a538cd /src/thread.rs | |
parent | f75b7b7879e1c3c9d12b02a42903d04eb26e8635 (diff) | |
download | mlua-87c10ca93dec7189330bdb0aad2daed5a1cd78fe.zip |
Sandboxing support
Diffstat (limited to 'src/thread.rs')
-rw-r--r-- | src/thread.rs | 60 |
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 { |