Don't allow 'callback outlive 'lua

This commit is contained in:
Alex Orlenko 2020-05-04 11:56:42 +01:00
parent e9c2b8d306
commit 7efcee853d
3 changed files with 80 additions and 3 deletions

View File

@ -190,6 +190,7 @@ impl Lua {
#[doc(hidden)]
pub fn entrypoint1<'lua, 'callback, R, F>(&'lua self, func: F) -> Result<c_int>
where
'lua: 'callback,
R: ToLua<'callback>,
F: 'static + Fn(&'callback Lua) -> Result<R>,
{
@ -446,6 +447,7 @@ impl Lua {
/// [`ToLuaMulti`]: trait.ToLuaMulti.html
pub fn create_function<'lua, 'callback, A, R, F>(&'lua self, func: F) -> Result<Function<'lua>>
where
'lua: 'callback,
A: FromLuaMulti<'callback>,
R: ToLuaMulti<'callback>,
F: 'static + Fn(&'callback Lua, A) -> Result<R>,
@ -466,6 +468,7 @@ impl Lua {
func: F,
) -> Result<Function<'lua>>
where
'lua: 'callback,
A: FromLuaMulti<'callback>,
R: ToLuaMulti<'callback>,
F: 'static + FnMut(&'callback Lua, A) -> Result<R>,
@ -522,6 +525,7 @@ impl Lua {
func: F,
) -> Result<Function<'lua>>
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<S>(&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<Function<'lua>> {
) -> Result<Function<'lua>>
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<Function<'lua>> {
) -> Result<Function<'lua>>
where
'lua: 'callback,
{
#[cfg(any(feature = "lua53", feature = "lua52"))]
self.load_from_std_lib(StdLib::COROUTINE)?;

View File

@ -0,0 +1,32 @@
use std::cell::RefCell;
use mlua::{Lua, Result, Table};
fn main() -> Result<()> {
thread_local! {
static BAD_TIME: RefCell<Option<Table<'static>>> = 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(())
}

View File

@ -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