diff --git a/sandbox.lua b/sandbox.lua index e8f2d78..66ff7c4 100644 --- a/sandbox.lua +++ b/sandbox.lua @@ -1,5 +1,4 @@ local BASE_ENV = {} - -- Non-safe : -- string.rep: can be used to allocate millions of bytes in 1 operation -- {set|get}metatable: can be used to modify the metatable of global objects (strings, integers) @@ -48,6 +47,15 @@ end) local string_rep = string.rep +local function copy(other) + if type(other) ~= 'table' then return other end + local c = {} + for k,v in pairs(other) do + c[copy(k)] = copy(v) + end + return c +end + local function cleanup() debug.sethook() string.rep = string_rep @@ -60,7 +68,9 @@ local function run(f, options) local limit = options.limit or 500000 - setfenv(f, BASE_ENV) + local env = copy(BASE_ENV) + + setfenv(f, env) -- I would love to be able to make step greater than 1 -- (say, 500000) but any value > 1 seems to choke with a simple while true do end diff --git a/spec/sandbox_spec.lua b/spec/sandbox_spec.lua index 36b528d..7aa0406 100644 --- a/spec/sandbox_spec.lua +++ b/spec/sandbox_spec.lua @@ -38,6 +38,11 @@ describe('sandbox', function() assert.equal('hellohello', string.rep('hello', 2)) end) + it('should not persist modifying the packages', function() + sandbox("string.foo = 1") + assert.is_nil(sandbox("return string.foo")) + end) + describe('when handling infinite loops', function() @@ -54,6 +59,9 @@ describe('sandbox', function() assert.no_has_error(function() sandbox("for i=1,100 do end") end) assert.has_error(function() sandbox("for i=1,100 do end", {limit = 50}) end) end) + end) + + end)