@@ -84,25 +84,31 @@ pub fn exec_settable(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
8484 let c = Instruction :: get_c ( instr) as usize ;
8585 let k = Instruction :: get_k ( instr) ;
8686
87- let frame = vm. current_frame ( ) ;
88- let base_ptr = frame. base_ptr ;
87+ // CRITICAL: Read all values BEFORE any metamethod calls
88+ // because metamethods can modify the register stack
89+ let ( table_value, key_value, set_value) = {
90+ let frame = vm. current_frame ( ) ;
91+ let base_ptr = frame. base_ptr ;
8992
90- let table = vm. register_stack [ base_ptr + a] ;
91- let key = vm. register_stack [ base_ptr + b] ;
92-
93- let value = if k {
94- // OPTIMIZATION: Get constant directly
95- let func_ptr = frame. get_function_ptr ( ) . ok_or_else ( || {
96- LuaError :: RuntimeError ( "Not a Lua function" . to_string ( ) )
97- } ) ?;
98- unsafe { ( * func_ptr) . borrow ( ) . chunk . constants . get ( c) . copied ( ) . ok_or_else ( || {
99- LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , c) )
100- } ) ? }
101- } else {
102- vm. register_stack [ base_ptr + c]
93+ let table = vm. register_stack [ base_ptr + a] ;
94+ let key = vm. register_stack [ base_ptr + b] ;
95+
96+ let value = if k {
97+ // OPTIMIZATION: Get constant directly
98+ let func_ptr = frame. get_function_ptr ( ) . ok_or_else ( || {
99+ LuaError :: RuntimeError ( "Not a Lua function" . to_string ( ) )
100+ } ) ?;
101+ unsafe { ( * func_ptr) . borrow ( ) . chunk . constants . get ( c) . copied ( ) . ok_or_else ( || {
102+ LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , c) )
103+ } ) ? }
104+ } else {
105+ vm. register_stack [ base_ptr + c]
106+ } ;
107+
108+ ( table, key, value)
103109 } ;
104110
105- vm. table_set_with_meta ( table , key , value ) ?;
111+ vm. table_set_with_meta ( table_value , key_value , set_value ) ?;
106112
107113 Ok ( DispatchAction :: Continue )
108114}
@@ -137,24 +143,30 @@ pub fn exec_seti(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
137143 let c = Instruction :: get_c ( instr) as usize ;
138144 let k = Instruction :: get_k ( instr) ;
139145
140- let frame = vm. current_frame ( ) ;
141- let base_ptr = frame. base_ptr ;
146+ // CRITICAL: Read all values BEFORE any metamethod calls
147+ // because metamethods can modify the register stack
148+ let ( table_value, key_value, set_value) = {
149+ let frame = vm. current_frame ( ) ;
150+ let base_ptr = frame. base_ptr ;
142151
143- let table = vm. register_stack [ base_ptr + a] ;
144- let key = crate :: LuaValue :: integer ( b as i64 ) ;
145-
146- let value = if k {
147- let func_ptr = frame. get_function_ptr ( ) . ok_or_else ( || {
148- LuaError :: RuntimeError ( "Not a Lua function" . to_string ( ) )
149- } ) ?;
150- unsafe { ( * func_ptr) . borrow ( ) . chunk . constants . get ( c) . copied ( ) . ok_or_else ( || {
151- LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , c) )
152- } ) ? }
153- } else {
154- vm. register_stack [ base_ptr + c]
152+ let table = vm. register_stack [ base_ptr + a] ;
153+ let key = crate :: LuaValue :: integer ( b as i64 ) ;
154+
155+ let value = if k {
156+ let func_ptr = frame. get_function_ptr ( ) . ok_or_else ( || {
157+ LuaError :: RuntimeError ( "Not a Lua function" . to_string ( ) )
158+ } ) ?;
159+ unsafe { ( * func_ptr) . borrow ( ) . chunk . constants . get ( c) . copied ( ) . ok_or_else ( || {
160+ LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , c) )
161+ } ) ? }
162+ } else {
163+ vm. register_stack [ base_ptr + c]
164+ } ;
165+
166+ ( table, key, value)
155167 } ;
156168
157- vm. table_set_with_meta ( table , key , value ) ?;
169+ vm. table_set_with_meta ( table_value , key_value , set_value ) ?;
158170
159171 Ok ( DispatchAction :: Continue )
160172}
@@ -203,27 +215,33 @@ pub fn exec_setfield(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
203215 let c = Instruction :: get_c ( instr) as usize ;
204216 let k = Instruction :: get_k ( instr) ;
205217
206- let frame = vm. current_frame ( ) ;
207- let base_ptr = frame. base_ptr ;
208-
209- let func_ptr = frame. get_function_ptr ( ) . ok_or_else ( || {
210- LuaError :: RuntimeError ( "Not a Lua function" . to_string ( ) )
211- } ) ?;
212- let key = unsafe { ( * func_ptr) . borrow ( ) . chunk . constants . get ( b) . copied ( ) . ok_or_else ( || {
213- LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , b) )
214- } ) ? } ;
218+ // CRITICAL: Read all values BEFORE any metamethod calls
219+ // because metamethods can modify the register stack
220+ let ( table_value, key_value, set_value) = {
221+ let frame = vm. current_frame ( ) ;
222+ let base_ptr = frame. base_ptr ;
223+
224+ let func_ptr = frame. get_function_ptr ( ) . ok_or_else ( || {
225+ LuaError :: RuntimeError ( "Not a Lua function" . to_string ( ) )
226+ } ) ?;
227+ let key = unsafe { ( * func_ptr) . borrow ( ) . chunk . constants . get ( b) . copied ( ) . ok_or_else ( || {
228+ LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , b) )
229+ } ) ? } ;
215230
216- let table = vm. register_stack [ base_ptr + a] ;
217-
218- let value = if k {
219- unsafe { ( * func_ptr) . borrow ( ) . chunk . constants . get ( c) . copied ( ) . ok_or_else ( || {
220- LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , c) )
221- } ) ? }
222- } else {
223- vm. register_stack [ base_ptr + c]
231+ let table = vm. register_stack [ base_ptr + a] ;
232+
233+ let value = if k {
234+ unsafe { ( * func_ptr) . borrow ( ) . chunk . constants . get ( c) . copied ( ) . ok_or_else ( || {
235+ LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , c) )
236+ } ) ? }
237+ } else {
238+ vm. register_stack [ base_ptr + c]
239+ } ;
240+
241+ ( table, key, value)
224242 } ;
225243
226- vm. table_set_with_meta ( table , key , value ) ?;
244+ vm. table_set_with_meta ( table_value , key_value , set_value ) ?;
227245
228246 Ok ( DispatchAction :: Continue )
229247}
@@ -269,34 +287,40 @@ pub fn exec_settabup(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
269287 let c = Instruction :: get_c ( instr) as usize ;
270288 let k = Instruction :: get_k ( instr) ;
271289
272- let frame = vm. current_frame ( ) ;
273- let base_ptr = frame. base_ptr ;
274-
275- let func_ptr = frame. get_function_ptr ( ) . ok_or_else ( || {
276- LuaError :: RuntimeError ( "Not a Lua function" . to_string ( ) )
277- } ) ?;
278- let func = unsafe { & * func_ptr } ;
279- let func_ref = func. borrow ( ) ;
280-
281- let key = func_ref. chunk . constants . get ( b) . copied ( ) . ok_or_else ( || {
282- LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , b) )
283- } ) ?;
290+ // CRITICAL: Read all values BEFORE any metamethod calls
291+ // because metamethods can modify the register stack
292+ let ( table_value, key_value, set_value) = {
293+ let frame = vm. current_frame ( ) ;
294+ let base_ptr = frame. base_ptr ;
295+
296+ let func_ptr = frame. get_function_ptr ( ) . ok_or_else ( || {
297+ LuaError :: RuntimeError ( "Not a Lua function" . to_string ( ) )
298+ } ) ?;
299+ let func = unsafe { & * func_ptr } ;
300+ let func_ref = func. borrow ( ) ;
301+
302+ let key = func_ref. chunk . constants . get ( b) . copied ( ) . ok_or_else ( || {
303+ LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , b) )
304+ } ) ?;
284305
285- let upvalue = func_ref. upvalues . get ( a) . ok_or_else ( || {
286- LuaError :: RuntimeError ( format ! ( "Invalid upvalue index: {}" , a) )
287- } ) ?;
306+ let upvalue = func_ref. upvalues . get ( a) . ok_or_else ( || {
307+ LuaError :: RuntimeError ( format ! ( "Invalid upvalue index: {}" , a) )
308+ } ) ?;
288309
289- let table = upvalue. get_value ( & vm. frames , & vm. register_stack ) ;
290-
291- let value = if k {
292- func_ref. chunk . constants . get ( c) . copied ( ) . ok_or_else ( || {
293- LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , c) )
294- } ) ?
295- } else {
296- vm. register_stack [ base_ptr + c]
310+ let table = upvalue. get_value ( & vm. frames , & vm. register_stack ) ;
311+
312+ let value = if k {
313+ func_ref. chunk . constants . get ( c) . copied ( ) . ok_or_else ( || {
314+ LuaError :: RuntimeError ( format ! ( "Invalid constant index: {}" , c) )
315+ } ) ?
316+ } else {
317+ vm. register_stack [ base_ptr + c]
318+ } ;
319+
320+ ( table, key, value)
297321 } ;
298322
299- vm. table_set_with_meta ( table , key , value ) ?;
323+ vm. table_set_with_meta ( table_value , key_value , set_value ) ?;
300324
301325 Ok ( DispatchAction :: Continue )
302326}
0 commit comments