summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorkyren <kerriganw@gmail.com>2018-08-05 11:54:33 -0400
committerkyren <kerriganw@gmail.com>2018-08-05 11:54:33 -0400
commita2615a8cbbd129d6b6d40ae3dd2cec232d8c7d4b (patch)
tree20abd46d6b3c648e1e1220a69a9544276d7614db /src
parent83669603687358c0bed59405aac6660b0967fe10 (diff)
downloadmlua-a2615a8cbbd129d6b6d40ae3dd2cec232d8c7d4b.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/scope.rs2
-rw-r--r--src/tests/mod.rs104
-rw-r--r--src/tests/scope.rs100
3 files changed, 104 insertions, 102 deletions
diff --git a/src/scope.rs b/src/scope.rs
index 476b5c1..58f440f 100644
--- a/src/scope.rs
+++ b/src/scope.rs
@@ -61,6 +61,7 @@ impl<'scope> Scope<'scope> {
A: FromLuaMulti<'callback>,
R: ToLuaMulti<'callback>,
F: 'scope + Fn(&'callback Lua, A) -> Result<R>,
+ 'scope: 'callback,
{
unsafe {
let f = Box::new(move |lua, args| {
@@ -106,6 +107,7 @@ impl<'scope> Scope<'scope> {
A: FromLuaMulti<'callback>,
R: ToLuaMulti<'callback>,
F: 'scope + FnMut(&'callback Lua, A) -> Result<R>,
+ 'scope: 'callback,
{
let func = RefCell::new(func);
self.create_function(move |lua, args| {
diff --git a/src/tests/mod.rs b/src/tests/mod.rs
index deed3bd..196bc45 100644
--- a/src/tests/mod.rs
+++ b/src/tests/mod.rs
@@ -1,21 +1,17 @@
mod function;
+mod scope;
mod string;
mod table;
mod thread;
mod types;
mod userdata;
-use std::cell::Cell;
use std::iter::FromIterator;
use std::panic::catch_unwind;
-use std::rc::Rc;
use std::sync::Arc;
use std::{error, fmt};
-use {
- Error, ExternalError, Function, Lua, Nil, Result, String, Table, UserData, UserDataMethods,
- Value, Variadic,
-};
+use {Error, ExternalError, Function, Lua, Nil, Result, String, Table, UserData, Value, Variadic};
#[test]
fn test_load() {
@@ -621,102 +617,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]
fn too_many_returns() {
let lua = Lua::new();
let f = lua
diff --git a/src/tests/scope.rs b/src/tests/scope.rs
new file mode 100644
index 0000000..1e4c255
--- /dev/null
+++ b/src/tests/scope.rs
@@ -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");
+}