Skip to content

Commit daa56a0

Browse files
committed
fix
1 parent 5a560bf commit daa56a0

File tree

3 files changed

+28
-14
lines changed

3 files changed

+28
-14
lines changed

crates/luars/src/lua_value/mod.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,11 @@ impl LuaUpvalue {
166166
drop(state);
167167
// Find the frame and read the register from global stack
168168
if let Some(frame) = frames.iter().find(|f| f.frame_id == frame_id) {
169-
if register < frame.top {
170-
let index = frame.base_ptr + register;
171-
if index < register_stack.len() {
172-
return register_stack[index];
173-
}
169+
// Don't check against frame.top, as it might be 0 for functions called with no args
170+
// Instead, just validate the absolute index is within the stack
171+
let index = frame.base_ptr + register;
172+
if index < register_stack.len() {
173+
return register_stack[index];
174174
}
175175
}
176176
LuaValue::nil()
@@ -193,11 +193,11 @@ impl LuaUpvalue {
193193
drop(state);
194194
// Find the frame and write the register to global stack
195195
if let Some(frame) = frames.iter_mut().find(|f| f.frame_id == frame_id) {
196-
if register < frame.top {
197-
let index = frame.base_ptr + register;
198-
if index < register_stack.len() {
199-
register_stack[index] = value;
200-
}
196+
// Don't check against frame.top, as it might be 0 for functions called with no args
197+
// Instead, just validate the absolute index is within the stack
198+
let index = frame.base_ptr + register;
199+
if index < register_stack.len() {
200+
register_stack[index] = value;
201201
}
202202
}
203203
}

crates/luars/src/lua_vm/dispatcher/control_instructions.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,11 @@ pub fn exec_tailcall(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
963963
.ok_or_else(|| LuaError::RuntimeError("Invalid function pointer".to_string()))?;
964964
let max_stack_size = unsafe { (*func_ptr).borrow().chunk.max_stack_size };
965965

966+
// CRITICAL: Before popping the frame, close all upvalues that point to it
967+
// This ensures that any closures created in this frame can still access
968+
// the captured values after the frame is destroyed
969+
vm.close_upvalues_from(base);
970+
966971
// Pop current frame (tail call optimization)
967972
let old_base = base; // Already extracted
968973
// return_count already extracted

crates/luars/src/lua_vm/mod.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,11 +1094,20 @@ impl LuaVM {
10941094
.iter()
10951095
.filter(|uv| {
10961096
// Check if this upvalue points to stack_pos or higher
1097+
// We need to find the frame that owns this upvalue
10971098
for frame in self.frames.iter() {
1098-
for reg_idx in 0..frame.top {
1099-
let absolute_pos = frame.base_ptr + reg_idx;
1100-
if absolute_pos >= stack_pos && uv.points_to(frame.frame_id, reg_idx) {
1101-
return true;
1099+
// Check all possible registers in this frame
1100+
// Use max_stack_size instead of top, because top might be 0 for functions
1101+
// called with no arguments (but they can still have local variables)
1102+
if let Some(func_ptr) = frame.function_value.as_function_ptr() {
1103+
let max_regs = unsafe { (*func_ptr).borrow().chunk.max_stack_size };
1104+
for reg_idx in 0..max_regs {
1105+
if uv.points_to(frame.frame_id, reg_idx) {
1106+
let absolute_pos = frame.base_ptr + reg_idx;
1107+
if absolute_pos >= stack_pos {
1108+
return true;
1109+
}
1110+
}
11021111
}
11031112
}
11041113
}

0 commit comments

Comments
 (0)