Files
moonwell-client-core/crates/benilla-lua/tests/oom.rs
T
Sam Sung c97fd03a57 Lua tables, ipairs and globals behave as the client's 5.0 (#1792)
benilla-lua's tables and globals now follow the client's Lua 5.0, not 5.1.

Tables:
- They size, fill and rehash as 5.0's ltable.c does: the hash part doubles (`0x6fab90`), and a log size of 0 is the shared dummy (`0x6fa601`).
- A hash part past 2^24 nodes raises `table overflow`.
- Constructors store every 32 items.
- A weak table's clearing removes the key, so `next` from it raises (`0x6f79d0`).
- A weak-keyed table keeps its string keys (`0x6f79f0`).

Globals and libraries:
- `ipairs` returns itself, and a second argument steps once.
- `setglobal` assigns the top of the stack.
- The state opens in the client's order, with no `_G`.

Each new test fails without its fix.

Fixes #1487
Fixes #1789
Fixes #1790
Fixes #1169

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 17:49:05 +07:00

59 lines
1.8 KiB
Rust

//! Allocations the allocator refuses: under an address-space limit, a concatenation whose result
//! cannot be built raises `not enough memory` where Rust's allocator would abort the process.
//! Its own test binary: the limit is the whole process's.
#[cfg(target_os = "linux")]
#[test]
fn a_concatenation_the_allocator_refuses_is_not_enough_memory() {
#[repr(C)]
struct Rlimit {
cur: u64,
max: u64,
}
extern "C" {
fn setrlimit(resource: i32, rlim: *const Rlimit) -> i32;
}
/// `RLIMIT_AS` on Linux.
const RLIMIT_AS: i32 = 9;
let gib = 1u64 << 30;
// SAFETY: a plain libc call with a valid struct; it only lowers this process's limit.
assert_eq!(
unsafe {
setrlimit(
RLIMIT_AS,
&Rlimit {
cur: 3 * gib / 2,
max: u64::MAX,
},
)
},
0
);
let got = std::thread::Builder::new()
.stack_size(2 << 20)
.spawn(|| {
let mut vm = benilla_lua::new_state();
let src = br#"local s = string.rep("x", 268435456)
local ok1, e1 = pcall(function() return s .. s .. s .. s .. s .. s end)
local ok2, e2 = pcall(function() return s .. s .. s .. s end)
return ok1, e1, ok2, e2, string.len(s .. "y")"#;
match vm.exec(src, b"=t") {
Ok(vs) => Ok(vs.into_iter().map(|v| vm.display(v)).collect::<Vec<_>>()),
Err(e) => Err(vm.display(e)),
}
})
.unwrap()
.join()
.unwrap();
assert_eq!(
got,
Ok(vec![
"false".into(),
"not enough memory".into(),
"false".into(),
"not enough memory".into(),
"268435457".into()
])
);
}