From 7efcee853d20236a1067eaf21539438dc9db15f1 Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Mon, 4 May 2020 11:56:42 +0100 Subject: [PATCH] Don't allow 'callback outlive 'lua --- src/lua.rs | 16 +++++++-- tests/compile_fail/static_callback_args.rs | 32 +++++++++++++++++ .../compile_fail/static_callback_args.stderr | 35 +++++++++++++++++++ 3 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 tests/compile_fail/static_callback_args.rs create mode 100644 tests/compile_fail/static_callback_args.stderr diff --git a/src/lua.rs b/src/lua.rs index 12feca9..f9b23d7 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -190,6 +190,7 @@ impl Lua { #[doc(hidden)] pub fn entrypoint1<'lua, 'callback, R, F>(&'lua self, func: F) -> Result where + 'lua: 'callback, R: ToLua<'callback>, F: 'static + Fn(&'callback Lua) -> Result, { @@ -446,6 +447,7 @@ impl Lua { /// [`ToLuaMulti`]: trait.ToLuaMulti.html pub fn create_function<'lua, 'callback, A, R, F>(&'lua self, func: F) -> Result> where + 'lua: 'callback, A: FromLuaMulti<'callback>, R: ToLuaMulti<'callback>, F: 'static + Fn(&'callback Lua, A) -> Result, @@ -466,6 +468,7 @@ impl Lua { func: F, ) -> Result> where + 'lua: 'callback, A: FromLuaMulti<'callback>, R: ToLuaMulti<'callback>, F: 'static + FnMut(&'callback Lua, A) -> Result, @@ -522,6 +525,7 @@ impl Lua { func: F, ) -> Result> where + 'lua: 'callback, A: FromLuaMulti<'callback>, R: ToLuaMulti<'callback>, F: 'static + Fn(&'callback Lua, A) -> FR, @@ -736,7 +740,7 @@ impl Lua { /// Equivalent to calling [`set_named_registry_value`] with a value of Nil. /// /// [`set_named_registry_value`]: #method.set_named_registry_value - pub fn unset_named_registry_value<'lua, S>(&'lua self, name: &S) -> Result<()> + pub fn unset_named_registry_value(&self, name: &S) -> Result<()> where S: ?Sized + AsRef<[u8]>, { @@ -1079,7 +1083,10 @@ impl Lua { pub(crate) fn create_callback<'lua, 'callback>( &'lua self, func: Callback<'callback, 'static>, - ) -> Result> { + ) -> Result> + where + 'lua: 'callback, + { unsafe extern "C" fn call_callback(state: *mut ffi::lua_State) -> c_int { callback_error(state, |nargs| { let func = @@ -1133,7 +1140,10 @@ impl Lua { pub(crate) fn create_async_callback<'lua, 'callback>( &'lua self, func: AsyncCallback<'callback, 'static>, - ) -> Result> { + ) -> Result> + where + 'lua: 'callback, + { #[cfg(any(feature = "lua53", feature = "lua52"))] self.load_from_std_lib(StdLib::COROUTINE)?; diff --git a/tests/compile_fail/static_callback_args.rs b/tests/compile_fail/static_callback_args.rs new file mode 100644 index 0000000..66dbf8b --- /dev/null +++ b/tests/compile_fail/static_callback_args.rs @@ -0,0 +1,32 @@ +use std::cell::RefCell; + +use mlua::{Lua, Result, Table}; + +fn main() -> Result<()> { + thread_local! { + static BAD_TIME: RefCell>> = RefCell::new(None); + } + + let lua = Lua::new(); + + lua.create_function(|_, table: Table| { + BAD_TIME.with(|bt| { + *bt.borrow_mut() = Some(table); + }); + Ok(()) + })? + .call::<_, ()>(lua.create_table()?)?; + + // In debug, this will panic with a reference leak before getting to the next part but + // it segfaults anyway. + drop(lua); + + BAD_TIME.with(|bt| { + println!( + "you're gonna have a bad time: {}", + bt.borrow().as_ref().unwrap().len().unwrap() + ); + }); + + Ok(()) +} diff --git a/tests/compile_fail/static_callback_args.stderr b/tests/compile_fail/static_callback_args.stderr new file mode 100644 index 0000000..561bcbe --- /dev/null +++ b/tests/compile_fail/static_callback_args.stderr @@ -0,0 +1,35 @@ +error[E0597]: `lua` does not live long enough + --> $DIR/static_callback_args.rs:12:5 + | +12 | lua.create_function(|_, table: Table| { + | -^^ + | | + | _____borrowed value does not live long enough + | | +13 | | BAD_TIME.with(|bt| { +14 | | *bt.borrow_mut() = Some(table); +15 | | }); +16 | | Ok(()) +17 | | })? + | |______- argument requires that `lua` is borrowed for `'static` +... +32 | } + | - `lua` dropped here while still borrowed + +error[E0505]: cannot move out of `lua` because it is borrowed + --> $DIR/static_callback_args.rs:22:10 + | +12 | lua.create_function(|_, table: Table| { + | --- + | | + | _____borrow of `lua` occurs here + | | +13 | | BAD_TIME.with(|bt| { +14 | | *bt.borrow_mut() = Some(table); +15 | | }); +16 | | Ok(()) +17 | | })? + | |______- argument requires that `lua` is borrowed for `'static` +... +22 | drop(lua); + | ^^^ move out of `lua` occurs here