Fix for a soundness bug around scope, don't allow callback parameters to escape
Also includes other fixes for compiletest_rs failures, and a small reorg of tests
This commit is contained in:
parent
8366960368
commit
a2615a8cbb
|
@ -61,6 +61,7 @@ impl<'scope> Scope<'scope> {
|
||||||
A: FromLuaMulti<'callback>,
|
A: FromLuaMulti<'callback>,
|
||||||
R: ToLuaMulti<'callback>,
|
R: ToLuaMulti<'callback>,
|
||||||
F: 'scope + Fn(&'callback Lua, A) -> Result<R>,
|
F: 'scope + Fn(&'callback Lua, A) -> Result<R>,
|
||||||
|
'scope: 'callback,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let f = Box::new(move |lua, args| {
|
let f = Box::new(move |lua, args| {
|
||||||
|
@ -106,6 +107,7 @@ impl<'scope> Scope<'scope> {
|
||||||
A: FromLuaMulti<'callback>,
|
A: FromLuaMulti<'callback>,
|
||||||
R: ToLuaMulti<'callback>,
|
R: ToLuaMulti<'callback>,
|
||||||
F: 'scope + FnMut(&'callback Lua, A) -> Result<R>,
|
F: 'scope + FnMut(&'callback Lua, A) -> Result<R>,
|
||||||
|
'scope: 'callback,
|
||||||
{
|
{
|
||||||
let func = RefCell::new(func);
|
let func = RefCell::new(func);
|
||||||
self.create_function(move |lua, args| {
|
self.create_function(move |lua, args| {
|
||||||
|
|
104
src/tests/mod.rs
104
src/tests/mod.rs
|
@ -1,21 +1,17 @@
|
||||||
mod function;
|
mod function;
|
||||||
|
mod scope;
|
||||||
mod string;
|
mod string;
|
||||||
mod table;
|
mod table;
|
||||||
mod thread;
|
mod thread;
|
||||||
mod types;
|
mod types;
|
||||||
mod userdata;
|
mod userdata;
|
||||||
|
|
||||||
use std::cell::Cell;
|
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::panic::catch_unwind;
|
use std::panic::catch_unwind;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{error, fmt};
|
use std::{error, fmt};
|
||||||
|
|
||||||
use {
|
use {Error, ExternalError, Function, Lua, Nil, Result, String, Table, UserData, Value, Variadic};
|
||||||
Error, ExternalError, Function, Lua, Nil, Result, String, Table, UserData, UserDataMethods,
|
|
||||||
Value, Variadic,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load() {
|
fn test_load() {
|
||||||
|
@ -620,102 +616,6 @@ fn test_mismatched_registry_key() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn scope_func() {
|
|
||||||
let lua = Lua::new();
|
|
||||||
|
|
||||||
let rc = Rc::new(Cell::new(0));
|
|
||||||
lua.scope(|scope| {
|
|
||||||
let r = rc.clone();
|
|
||||||
let f = scope
|
|
||||||
.create_function(move |_, ()| {
|
|
||||||
r.set(42);
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
lua.globals().set("bad", f.clone()).unwrap();
|
|
||||||
f.call::<_, ()>(()).unwrap();
|
|
||||||
assert_eq!(Rc::strong_count(&rc), 2);
|
|
||||||
});
|
|
||||||
assert_eq!(rc.get(), 42);
|
|
||||||
assert_eq!(Rc::strong_count(&rc), 1);
|
|
||||||
|
|
||||||
match lua
|
|
||||||
.globals()
|
|
||||||
.get::<_, Function>("bad")
|
|
||||||
.unwrap()
|
|
||||||
.call::<_, ()>(())
|
|
||||||
{
|
|
||||||
Err(Error::CallbackError { .. }) => {}
|
|
||||||
r => panic!("improper return for destructed function: {:?}", r),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn scope_drop() {
|
|
||||||
let lua = Lua::new();
|
|
||||||
|
|
||||||
struct MyUserdata(Rc<()>);
|
|
||||||
impl UserData for MyUserdata {
|
|
||||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
|
||||||
methods.add_method("method", |_, _, ()| Ok(()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let rc = Rc::new(());
|
|
||||||
|
|
||||||
lua.scope(|scope| {
|
|
||||||
lua.globals()
|
|
||||||
.set(
|
|
||||||
"test",
|
|
||||||
scope.create_userdata(MyUserdata(rc.clone())).unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(Rc::strong_count(&rc), 2);
|
|
||||||
});
|
|
||||||
assert_eq!(Rc::strong_count(&rc), 1);
|
|
||||||
|
|
||||||
match lua.exec::<()>("test:method()", None) {
|
|
||||||
Err(Error::CallbackError { .. }) => {}
|
|
||||||
r => panic!("improper return for destructed userdata: {:?}", r),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn scope_capture() {
|
|
||||||
let lua = Lua::new();
|
|
||||||
|
|
||||||
let mut i = 0;
|
|
||||||
lua.scope(|scope| {
|
|
||||||
scope
|
|
||||||
.create_function_mut(|_, ()| {
|
|
||||||
i = 42;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
.call::<_, ()>(())
|
|
||||||
.unwrap();
|
|
||||||
});
|
|
||||||
assert_eq!(i, 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn outer_lua_access() {
|
|
||||||
let lua = Lua::new();
|
|
||||||
let table = lua.create_table().unwrap();
|
|
||||||
lua.scope(|scope| {
|
|
||||||
scope
|
|
||||||
.create_function_mut(|_, ()| {
|
|
||||||
table.set("a", "b").unwrap();
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
.call::<_, ()>(())
|
|
||||||
.unwrap();
|
|
||||||
});
|
|
||||||
assert_eq!(table.get::<_, String>("a").unwrap(), "b");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn too_many_returns() {
|
fn too_many_returns() {
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use {Error, Function, Lua, String, UserData, UserDataMethods};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn scope_func() {
|
||||||
|
let lua = Lua::new();
|
||||||
|
|
||||||
|
let rc = Rc::new(Cell::new(0));
|
||||||
|
lua.scope(|scope| {
|
||||||
|
let r = rc.clone();
|
||||||
|
let f = scope
|
||||||
|
.create_function(move |_, ()| {
|
||||||
|
r.set(42);
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
lua.globals().set("bad", f.clone()).unwrap();
|
||||||
|
f.call::<_, ()>(()).unwrap();
|
||||||
|
assert_eq!(Rc::strong_count(&rc), 2);
|
||||||
|
});
|
||||||
|
assert_eq!(rc.get(), 42);
|
||||||
|
assert_eq!(Rc::strong_count(&rc), 1);
|
||||||
|
|
||||||
|
match lua
|
||||||
|
.globals()
|
||||||
|
.get::<_, Function>("bad")
|
||||||
|
.unwrap()
|
||||||
|
.call::<_, ()>(())
|
||||||
|
{
|
||||||
|
Err(Error::CallbackError { .. }) => {}
|
||||||
|
r => panic!("improper return for destructed function: {:?}", r),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn scope_drop() {
|
||||||
|
let lua = Lua::new();
|
||||||
|
|
||||||
|
struct MyUserdata(Rc<()>);
|
||||||
|
impl UserData for MyUserdata {
|
||||||
|
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||||
|
methods.add_method("method", |_, _, ()| Ok(()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let rc = Rc::new(());
|
||||||
|
|
||||||
|
lua.scope(|scope| {
|
||||||
|
lua.globals()
|
||||||
|
.set(
|
||||||
|
"test",
|
||||||
|
scope.create_userdata(MyUserdata(rc.clone())).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(Rc::strong_count(&rc), 2);
|
||||||
|
});
|
||||||
|
assert_eq!(Rc::strong_count(&rc), 1);
|
||||||
|
|
||||||
|
match lua.exec::<()>("test:method()", None) {
|
||||||
|
Err(Error::CallbackError { .. }) => {}
|
||||||
|
r => panic!("improper return for destructed userdata: {:?}", r),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn scope_capture() {
|
||||||
|
let lua = Lua::new();
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
lua.scope(|scope| {
|
||||||
|
scope
|
||||||
|
.create_function_mut(|_, ()| {
|
||||||
|
i = 42;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.call::<_, ()>(())
|
||||||
|
.unwrap();
|
||||||
|
});
|
||||||
|
assert_eq!(i, 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn outer_lua_access() {
|
||||||
|
let lua = Lua::new();
|
||||||
|
let table = lua.create_table().unwrap();
|
||||||
|
lua.scope(|scope| {
|
||||||
|
scope
|
||||||
|
.create_function_mut(|_, ()| {
|
||||||
|
table.set("a", "b").unwrap();
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.call::<_, ()>(())
|
||||||
|
.unwrap();
|
||||||
|
});
|
||||||
|
assert_eq!(table.get::<_, String>("a").unwrap(), "b");
|
||||||
|
}
|
|
@ -7,5 +7,6 @@ use rlua::*;
|
||||||
fn main() {
|
fn main() {
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
let _ = catch_unwind(|| lua.create_table().unwrap());
|
let _ = catch_unwind(|| lua.create_table().unwrap());
|
||||||
//~^ error: the trait bound `std::cell::UnsafeCell<()>: std::panic::RefUnwindSafe` is not satisfied in `rlua::Lua`
|
//~^ error: the type `std::cell::UnsafeCell<()>` may contain interior mutability and a reference
|
||||||
|
// may not be safely transferrable across a catch_unwind boundary
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,5 +8,6 @@ fn main() {
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
let table = lua.create_table().unwrap();
|
let table = lua.create_table().unwrap();
|
||||||
let _ = catch_unwind(move || table.set("a", "b").unwrap());
|
let _ = catch_unwind(move || table.set("a", "b").unwrap());
|
||||||
//~^ error: the trait bound `std::cell::UnsafeCell<()>: std::panic::RefUnwindSafe` is not satisfied in `rlua::Lua`
|
//~^ error: the type `std::cell::UnsafeCell<()>` may contain interior mutability and a reference
|
||||||
|
// may not be safely transferrable across a catch_unwind boundary
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
extern crate rlua;
|
||||||
|
|
||||||
|
use rlua::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
struct Test {
|
||||||
|
field: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
let lua = Lua::new();
|
||||||
|
let mut outer: Option<Table> = None;
|
||||||
|
lua.scope(|scope| {
|
||||||
|
let f = scope
|
||||||
|
.create_function_mut(|_, t: Table| {
|
||||||
|
outer = Some(t);
|
||||||
|
//~^ error: `*outer` does not live long enough
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
f.call::<_, ()>(lua.create_table()).unwrap();
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
extern crate rlua;
|
||||||
|
|
||||||
|
use rlua::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
struct Test {
|
||||||
|
field: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
let lua = Lua::new();
|
||||||
|
lua.scope(|scope| {
|
||||||
|
let mut inner: Option<Table> = None;
|
||||||
|
let f = scope
|
||||||
|
.create_function_mut(|_, t: Table| {
|
||||||
|
inner = Some(t);
|
||||||
|
//~^ error: `inner` does not live long enough
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
f.call::<_, ()>(lua.create_table()).unwrap();
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue