added refs param

This commit is contained in:
kikito 2013-09-03 18:07:03 +02:00
parent ee9c0f9164
commit 36fb0929e0
3 changed files with 50 additions and 6 deletions

View File

@ -34,6 +34,17 @@ Usage
-- It is also possible to use the env option to add additional variables to the environment -- It is also possible to use the env option to add additional variables to the environment
sandbox('return foo', {env = {foo = 'This was on the environment'}}) sandbox('return foo', {env = {foo = 'This was on the environment'}})
-- The variables defined on the env are deep-copied and changes on them will not be persisted
local env = {foo = "can't touch this"}
sandbox('foo = "bar"', {env = env})
assert(env.foo = "can't touch this")
-- If you want to modify variables from inside the sandbox, use the refs option:
local refs = {foo = "kindof insecure"}
sandbox('foo = "changed"', {refs = refs})
assert(refs.foo = "changed")
Installation Installation
============ ============

View File

@ -67,9 +67,10 @@ copy = function(other)
end end
local function cleanup() local function cleanup(sandboxed_env, refs)
debug.sethook() debug.sethook()
string.rep = string_rep string.rep = string_rep
for k,_ in pairs(refs) do refs[k] = sandboxed_env[k] end
end end
local function run(f, options) local function run(f, options)
@ -79,8 +80,10 @@ local function run(f, options)
local quota = options.quota or 500000 local quota = options.quota or 500000
local env = options.env or {} local env = options.env or {}
local refs = options.refs or {}
local sandboxed_env = merge(copy(BASE_ENV), env) local sandboxed_env = merge(copy(BASE_ENV), env)
for k,v in pairs(refs) do sandboxed_env[k] = v end
setfenv(f, sandboxed_env) setfenv(f, sandboxed_env)
@ -93,7 +96,7 @@ local function run(f, options)
local timeout = function(str) local timeout = function(str)
instructions_count = instructions_count + 1 instructions_count = instructions_count + 1
if instructions_count >= quota then if instructions_count >= quota then
cleanup() cleanup(sandboxed_env, refs)
error('Quota exceeded: ' .. tostring(instructions_count) .. '/' .. tostring(quota) .. ' instructions') error('Quota exceeded: ' .. tostring(instructions_count) .. '/' .. tostring(quota) .. ' instructions')
end end
end end
@ -102,7 +105,7 @@ local function run(f, options)
local ok, result = pcall(f) local ok, result = pcall(f)
cleanup() cleanup(sandboxed_env, refs)
if not ok then error(result) end if not ok then error(result) end
return result return result

View File

@ -58,19 +58,49 @@ describe('sandbox', function()
it('accepts a quota param', function() it('accepts a quota param', function()
assert.no_has_error(function() sandbox("for i=1,100 do end") end) assert.no_has_error(function() sandbox("for i=1,100 do end") end)
assert.has_error(function() sandbox("for i=1,100 do end", {quota = 50}) end) assert.has_error(function() sandbox("for i=1,100 do end", {quota = 20}) end)
end) end)
end) end)
describe('when given an env', function() describe('when given an env option', function()
it('is available on the sandboxed env', function() it('is available on the sandboxed env', function()
assert.equal(1, sandbox("return foo", {env = {foo = 1}})) assert.equal(1, sandbox("return foo", {env = {foo = 1}}))
end) end)
it('does not hide previous env', function() it('does not hide base env', function()
assert.equal('HELLO', sandbox("return string.upper(foo)", {env = {foo = 'hello'}})) assert.equal('HELLO', sandbox("return string.upper(foo)", {env = {foo = 'hello'}}))
end) end)
it('can not modify the env', function()
local env = {foo = 1}
sandbox("foo = 2", {env = env})
assert.equal(env.foo, 1)
end)
end)
describe('when given a refs option', function()
it('is available on the sandboxed env', function()
assert.equal(1, sandbox("return foo", {refs = {foo = 1}}))
end)
it('does not hide base env', function()
assert.equal('HELLO', sandbox("return string.upper(foo)", {refs = {foo = 'hello'}}))
end)
it('can modify the refs', function()
local refs = {foo = 1}
sandbox("foo = 2", {refs = refs})
assert.equal(refs.foo, 2)
end)
it('can modify the ref tables keys', function()
local refs = {items = {quantity = 1}}
sandbox("items.quantity = 2", {refs = refs})
assert.equal(refs.items.quantity, 2)
end)
end) end)