Skip to content

Commit

Permalink
Ensure that buffer with Luau compiled code is always freed
Browse files Browse the repository at this point in the history
  • Loading branch information
khvzak committed Nov 29, 2024
1 parent 55a5d7e commit 7a3f19b
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 4 deletions.
15 changes: 13 additions & 2 deletions mlua-sys/src/luau/compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,16 @@ pub unsafe fn luaL_loadbufferenv(
mut size: usize,
name: *const c_char,
mode: *const c_char,
env: c_int,
mut env: c_int,
) -> c_int {
extern "C" {
fn free(p: *mut c_void);
}

unsafe extern "C-unwind" fn data_dtor(data: *mut c_void) {
free(*(data as *mut *mut c_char) as *mut c_void);
}

let chunk_is_text = size == 0 || (*data as u8) >= b'\t';
if !mode.is_null() {
let modeb = CStr::from_ptr(mode).to_bytes();
Expand All @@ -345,9 +349,16 @@ pub unsafe fn luaL_loadbufferenv(
}

if chunk_is_text {
if env < 0 {
env -= 1;
}
let data_ud = lua_newuserdatadtor(L, mem::size_of::<*mut c_char>(), data_dtor) as *mut *mut c_char;
let data = luau_compile_(data, size, ptr::null_mut(), &mut size);
ptr::write(data_ud, data);
// By deferring the `free(data)` to the userdata destructor, we ensure that
// even if `luau_load` throws an error, the `data` is still released.
let ok = luau_load(L, name, data, size, env) == 0;
free(data as *mut c_void);
lua_replace(L, -2); // replace data with the result
if !ok {
return LUA_ERRSYNTAX;
}
Expand Down
4 changes: 2 additions & 2 deletions src/state/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,10 @@ impl RawLua {
Some(ChunkMode::Text) => cstr!("t"),
None => cstr!("bt"),
};
let status = if cfg!(not(feature = "luau")) || self.unlikely_memory_error() {
let status = if self.unlikely_memory_error() {
self.load_chunk_inner(state, name, env, mode, source)
} else {
// Only Luau can trigger an exception during chunk loading
// Luau and Lua 5.2 can trigger an exception during chunk loading
protect_lua!(state, 0, 1, |state| {
self.load_chunk_inner(state, name, env, mode, source)
})?
Expand Down

0 comments on commit 7a3f19b

Please sign in to comment.