Create your own sandbox (or several sandboxes if each one has different requirements) and move the untrusted code to the sandbox one fragment at a time. In my quick tests, cli, both 5.1 and 5.2 will run functions that were defined outside the sandbox without changes. To use the Doug example, suppose display
is part of your pre-existing code that uses print
:
-- 5.1 local function display(...) print(...) end local script = loadstring "display(math.log(2, 3))" local env = {display = display, math = math, string = string} setfenv(script, env) print(pcall(script)) -- 5.2 local function display(...) print(...) end local script = loadstring "display(math.log(2, 3))" local e=_ENV _ENV={display = display, math = math, string = string} e.print(e.pcall(script)) _ENV=e
Please note that in both of the above examples, the display
function uses print
without changing this code, since you were not in the sandbox when this function was created.
In the past, I saved a local pointer to the environment without the sandbox, but I cannot reproduce the situation when it is necessary in my quick cli tests. If you can come up with an example, I might come up with a workaround for which the variable e
is not required. Here is an example of this code using 5.2:
local e=_ENV for k,v in e.pairs(value) do -- iterate end
another example, for my read-only table code, I use e
again:
function ro_table (t) local t = t if t then return e.setmetatable({}, { __index=t, __newindex= function(_,_,_) e.error ("Attempt to modify read-only table") end, }) else return nil end end