Skip to content

Commit 634e5d4

Browse files
committed
Reduce collectgarbage options in sandboxed mode
See https://luau.org/sandbox#library
1 parent 05d6c20 commit 634e5d4

File tree

3 files changed

+22
-8
lines changed

3 files changed

+22
-8
lines changed

src/luau/mod.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::ptr;
55
use crate::chunk::ChunkMode;
66
use crate::error::Result;
77
use crate::function::Function;
8-
use crate::state::{callback_error_ext, Lua};
8+
use crate::state::{callback_error_ext, ExtraData, Lua};
99
use crate::traits::{FromLuaMulti, IntoLua};
1010

1111
pub use require::{NavigateError, Require, TextRequirer};
@@ -45,16 +45,17 @@ unsafe extern "C-unwind" fn lua_collectgarbage(state: *mut ffi::lua_State) -> c_
4545
let option = ffi::luaL_optstring(state, 1, cstr!("collect"));
4646
let option = CStr::from_ptr(option);
4747
let arg = ffi::luaL_optinteger(state, 2, 0);
48+
let is_sandboxed = (*ExtraData::get(state)).sandboxed;
4849
match option.to_str() {
49-
Ok("collect") => {
50+
Ok("collect") if !is_sandboxed => {
5051
ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0);
5152
0
5253
}
53-
Ok("stop") => {
54+
Ok("stop") if !is_sandboxed => {
5455
ffi::lua_gc(state, ffi::LUA_GCSTOP, 0);
5556
0
5657
}
57-
Ok("restart") => {
58+
Ok("restart") if !is_sandboxed => {
5859
ffi::lua_gc(state, ffi::LUA_GCRESTART, 0);
5960
0
6061
}
@@ -64,12 +65,12 @@ unsafe extern "C-unwind" fn lua_collectgarbage(state: *mut ffi::lua_State) -> c_
6465
ffi::lua_pushnumber(state, kbytes + kbytes_rem / 1024.0);
6566
1
6667
}
67-
Ok("step") => {
68+
Ok("step") if !is_sandboxed => {
6869
let res = ffi::lua_gc(state, ffi::LUA_GCSTEP, arg as _);
6970
ffi::lua_pushboolean(state, res);
7071
1
7172
}
72-
Ok("isrunning") => {
73+
Ok("isrunning") if !is_sandboxed => {
7374
let res = ffi::lua_gc(state, ffi::LUA_GCISRUNNING, 0);
7475
ffi::lua_pushboolean(state, res);
7576
1

src/state/extra.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub(crate) struct ExtraData {
8989
#[cfg(feature = "luau")]
9090
pub(crate) running_gc: bool,
9191
#[cfg(feature = "luau")]
92-
pub(super) sandboxed: bool,
92+
pub(crate) sandboxed: bool,
9393
#[cfg(feature = "luau")]
9494
pub(super) compiler: Option<Compiler>,
9595
#[cfg(feature = "luau-jit")]
@@ -212,7 +212,7 @@ impl ExtraData {
212212
self.weak.write(WeakLua(XRc::downgrade(raw)));
213213
}
214214

215-
pub(super) unsafe fn get(state: *mut ffi::lua_State) -> *mut Self {
215+
pub(crate) unsafe fn get(state: *mut ffi::lua_State) -> *mut Self {
216216
#[cfg(feature = "luau")]
217217
if cfg!(not(feature = "module")) {
218218
// In the main app we can use `lua_callbacks` to access ExtraData

tests/luau.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,14 @@ fn test_sandbox() -> Result<()> {
196196
co.sandbox()?;
197197
assert_eq!(co.resume::<Option<i32>>(())?, Some(123));
198198

199+
// collectgarbage should be restricted in sandboxed mode
200+
let collectgarbage = lua.globals().get::<Function>("collectgarbage")?;
201+
for arg in ["collect", "stop", "restart", "step", "isrunning"] {
202+
let err = collectgarbage.call::<()>(arg).err().unwrap().to_string();
203+
assert!(err.contains("collectgarbage called with invalid option"));
204+
}
205+
assert!(collectgarbage.call::<u64>("count").unwrap() > 0);
206+
199207
lua.sandbox(false)?;
200208

201209
// Previously set variable `global` should be cleared now
@@ -205,6 +213,11 @@ fn test_sandbox() -> Result<()> {
205213
let table = lua.globals().get::<Table>("table")?;
206214
table.set("test", "test")?;
207215

216+
// collectgarbage should work now
217+
for arg in ["collect", "stop", "restart", "count", "step", "isrunning"] {
218+
collectgarbage.call::<()>(arg).unwrap();
219+
}
220+
208221
Ok(())
209222
}
210223

0 commit comments

Comments
 (0)