Fix argument bugs with pcall / xpcall, add tests for it

This commit is contained in:
kyren 2017-08-02 10:42:18 -04:00
parent f6cefca916
commit f9f3d05804
2 changed files with 41 additions and 2 deletions

View File

@ -889,6 +889,35 @@ fn coroutine_panic() {
thrd.resume::<_, ()>(()).unwrap(); thrd.resume::<_, ()>(()).unwrap();
} }
#[test]
fn test_pcall_xpcall() {
let lua = Lua::new();
// make sure that we handle not enough arguments
assert!(lua.exec::<()>("pcall()", None).is_err());
assert!(lua.exec::<()>("xpcall()", None).is_err());
assert!(lua.exec::<()>("xpcall(function() end)", None).is_err());
lua.exec::<()>(
r#"
pcall_error = nil
_, pcall_error = pcall(error, "testerror")
xpcall_error = nil
xpcall(error, function(err) xpcall_error = err end, "testerror")
"#,
None,
).unwrap();
assert_eq!(
lua.globals().get::<_, String>("pcall_error").unwrap(),
"testerror"
);
assert_eq!(
lua.globals().get::<_, String>("xpcall_error").unwrap(),
"testerror"
);
}
// Need to use compiletest-rs or similar to make sure these don't compile. // Need to use compiletest-rs or similar to make sure these don't compile.
/* /*

View File

@ -432,7 +432,11 @@ pub unsafe fn resume_with_traceback(
// A variant of pcall that does not allow lua to catch panic errors from callback_error // A variant of pcall that does not allow lua to catch panic errors from callback_error
pub unsafe extern "C" fn safe_pcall(state: *mut ffi::lua_State) -> c_int { pub unsafe extern "C" fn safe_pcall(state: *mut ffi::lua_State) -> c_int {
if ffi::lua_pcall(state, ffi::lua_gettop(state) - 1, ffi::LUA_MULTRET, 0) != ffi::LUA_OK { let top = ffi::lua_gettop(state);
if top == 0 {
push_string(state, "not enough arguments to pcall");
ffi::lua_error(state);
} else if ffi::lua_pcall(state, top - 1, ffi::LUA_MULTRET, 0) != ffi::LUA_OK {
if is_wrapped_panic(state, -1) { if is_wrapped_panic(state, -1) {
ffi::lua_error(state); ffi::lua_error(state);
} }
@ -459,10 +463,16 @@ pub unsafe extern "C" fn safe_xpcall(state: *mut ffi::lua_State) -> c_int {
} }
} }
let top = ffi::lua_gettop(state);
if top < 2 {
push_string(state, "not enough arguments to xpcall");
ffi::lua_error(state);
}
ffi::lua_pushvalue(state, 2); ffi::lua_pushvalue(state, 2);
ffi::lua_pushcclosure(state, xpcall_msgh, 1); ffi::lua_pushcclosure(state, xpcall_msgh, 1);
ffi::lua_copy(state, 1, 2); ffi::lua_copy(state, 1, 2);
ffi::lua_insert(state, 1); ffi::lua_replace(state, 1);
let res = ffi::lua_pcall(state, ffi::lua_gettop(state) - 2, ffi::LUA_MULTRET, 1); let res = ffi::lua_pcall(state, ffi::lua_gettop(state) - 2, ffi::LUA_MULTRET, 1);
if res != ffi::LUA_OK { if res != ffi::LUA_OK {