use luaur_rt::Lua;
fn pcall_err(body: &str) -> String {
let lua = Lua::new();
let code = format!(
"local ok, err = pcall(function() {body} end)\n\
if ok then return '' else return tostring(err) end"
);
lua.load(&code)
.set_name("regress")
.eval::<String>()
.expect("chunk should compile and run under pcall")
}
fn assert_no_overflow(what: &str, err: &str) {
assert!(
!err.contains("overflow") && !err.contains("attempt to"),
"{what}: builtin panicked on a boundary argument instead of handling it: {err:?}"
);
}
#[test]
fn math_randomseed_negative_does_not_overflow() {
let err = pcall_err("math.randomseed(-1)");
assert_no_overflow("math.randomseed(-1)", &err);
assert!(
err.is_empty(),
"math.randomseed(-1) should succeed: {err:?}"
);
for s in ["-2147483648", "2147483647", "4294967295"] {
let e = pcall_err(&format!("math.randomseed({s})"));
assert_no_overflow("math.randomseed", &e);
}
}
#[test]
fn buffer_copy_intmin_source_offset() {
let err = pcall_err("buffer.copy(buffer.create(8), 0, buffer.create(8), -2147483648)");
assert_no_overflow("buffer.copy", &err);
assert!(
err.is_empty() || err.contains("out of bounds"),
"buffer.copy unexpected error: {err:?}"
);
}
#[test]
fn buffer_fill_intmin_offset() {
let err = pcall_err("buffer.fill(buffer.create(8), -2147483648, 1)");
assert_no_overflow("buffer.fill", &err);
assert!(
err.is_empty() || err.contains("out of bounds"),
"buffer.fill unexpected error: {err:?}"
);
}
#[test]
fn table_concat_intmin_start_index() {
let err = pcall_err("return table.concat({1, 2, 3}, '', -2147483648)");
assert_no_overflow("table.concat", &err);
assert!(
err.contains("invalid value") || err.is_empty(),
"table.concat unexpected error: {err:?}"
);
}
#[test]
fn table_unpack_full_int_range_rejected() {
let err = pcall_err("return table.unpack({1, 2, 3}, -2147483648, 2147483647)");
assert!(
err.contains("too many results"),
"table.unpack must reject a full-range request: {err:?}"
);
}
#[test]
fn table_find_intmax_element_does_not_overflow() {
let err = pcall_err("return table.find({[2147483647] = false}, true, 2147483647)");
assert_no_overflow("table.find", &err);
assert!(
err.is_empty(),
"table.find should return nil cleanly: {err:?}"
);
let lua = Lua::new();
let idx: i64 = lua
.load("return table.find({10, 20, 30}, 20)")
.eval()
.expect("table.find ordinary path");
assert_eq!(idx, 2);
}
#[test]
fn ordinary_stdlib_calls_still_work() {
let lua = Lua::new();
let sum: i64 = lua
.load("local b = buffer.create(8); buffer.fill(b, 0, 7); return buffer.readu8(b, 3)")
.eval()
.expect("buffer.fill/readu8 ordinary path");
assert_eq!(sum, 7);
let s: String = lua
.load("return table.concat({'a', 'b', 'c'}, '-')")
.eval()
.expect("table.concat ordinary path");
assert_eq!(s, "a-b-c");
let n: i64 = lua
.load("return select('#', table.unpack({10, 20, 30}))")
.eval()
.expect("table.unpack ordinary path");
assert_eq!(n, 3);
}