From 39d3201848fe4bbccf93075ef4b0b8b71ca1719f Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Tue, 26 May 2026 23:13:44 +0100 Subject: [PATCH] Prevent `XRc` overflow when dropping `RawLua` with foreign Lua state Calling `lua_close` triggers GC collection of the `ExtraData` that cascades to `RawLua::drop` where extra is already decremented to 0, causing a subtraction overflow. --- src/state/raw.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/state/raw.rs b/src/state/raw.rs index dcc860a..06b9bfa 100644 --- a/src/state/raw.rs +++ b/src/state/raw.rs @@ -1,7 +1,7 @@ use std::any::TypeId; use std::cell::{Cell, UnsafeCell}; use std::ffi::CStr; -use std::mem; +use std::mem::{self, ManuallyDrop}; use std::os::raw::{c_char, c_int, c_void}; use std::panic::resume_unwind; use std::ptr::{self, NonNull}; @@ -56,7 +56,7 @@ pub struct RawLua { // The state is dynamic and depends on context pub(super) state: Cell<*mut ffi::lua_State>, pub(super) main_state: Option>, - pub(super) extra: XRc>, + pub(super) extra: ManuallyDrop>>, owned: bool, } @@ -82,6 +82,9 @@ impl Drop for RawLua { if !mem_state.is_null() { drop(Box::from_raw(mem_state)); } + + // Drop the `ExtraData` reference after `lua_close` has collected the registry entry + ManuallyDrop::drop(&mut self.extra); } } } @@ -245,7 +248,7 @@ impl RawLua { state: Cell::new(state), // Make sure that we don't store current state as main state (if it's not available) main_state: get_main_state(state).and_then(NonNull::new), - extra: XRc::clone(&extra), + extra: ManuallyDrop::new(XRc::clone(&extra)), owned, })); (*extra.get()).set_lua(&rawlua);