mirror of
https://github.com/kikito/lua-sandbox.git
synced 2024-12-18 03:04:20 +00:00
feat(sandbox) explicitly drop support of quotas on LuaJIT
The solution we use in PUC Rio Lua (with debug.sethook) simply does not work in LuaJIT. * We have added a `sandbox.quota_supported` field to signal this feature (or lack of thereof) * We explicitly return an error if `options.quota` is passed on a LuaJIT environment, in order to prevent LuaJIT users from believing that they are protected against infinite loops.
This commit is contained in:
parent
242a749c4d
commit
71223d4fe9
@ -65,7 +65,7 @@ sandbox.run('while true do end') -- raise errors after 500000 instructions
|
|||||||
sandbox.run('while true do end', {quota=10000}) -- raise error after 10000 instructions
|
sandbox.run('while true do end', {quota=10000}) -- raise error after 10000 instructions
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that if the quota is low enough, sandboxed functions that do lots of calculations might fail:
|
If the quota is low enough, sandboxed functions that do lots of calculations might fail:
|
||||||
|
|
||||||
``` lua
|
``` lua
|
||||||
local f = function()
|
local f = function()
|
||||||
@ -77,6 +77,8 @@ end
|
|||||||
sandbox.run(f, {quota=100}) -- raises error before the function ends
|
sandbox.run(f, {quota=100}) -- raises error before the function ends
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: This feature is not available in LuaJIT
|
||||||
|
|
||||||
### options.env
|
### options.env
|
||||||
|
|
||||||
Use the `env` option to inject additional variables to the environment in which the sandboxed function is executed.
|
Use the `env` option to inject additional variables to the environment in which the sandboxed function is executed.
|
||||||
|
11
sandbox.lua
11
sandbox.lua
@ -25,9 +25,13 @@ local sandbox = {
|
|||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
]]
|
]],
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- quotas don't work in LuaJIT since debug.sethook works differently there
|
||||||
|
local quota_supported = type(_G.jit) == "nil"
|
||||||
|
sandbox.quota_supported = quota_supported
|
||||||
|
|
||||||
-- PUC-Rio Lua 5.1 does not support deactivation of binary code
|
-- PUC-Rio Lua 5.1 does not support deactivation of binary code
|
||||||
local mode_supported = _ENV or type(_G.jit) == "table"
|
local mode_supported = _ENV or type(_G.jit) == "table"
|
||||||
@ -125,6 +129,9 @@ function sandbox.protect(code, options)
|
|||||||
options = options or {}
|
options = options or {}
|
||||||
|
|
||||||
local quota = false
|
local quota = false
|
||||||
|
if options.quota and not quota_supported then
|
||||||
|
error("options.quota is not supported on this environment (usually LuaJIT). Please unset options.quota")
|
||||||
|
end
|
||||||
if options.quota ~= false then
|
if options.quota ~= false then
|
||||||
quota = options.quota or 500000
|
quota = options.quota or 500000
|
||||||
end
|
end
|
||||||
@ -148,7 +155,7 @@ function sandbox.protect(code, options)
|
|||||||
|
|
||||||
return function(...)
|
return function(...)
|
||||||
|
|
||||||
if quota then
|
if quota and quota_supported then
|
||||||
local timeout = function()
|
local timeout = function()
|
||||||
cleanup()
|
cleanup()
|
||||||
error('Quota exceeded: ' .. tostring(quota))
|
error('Quota exceeded: ' .. tostring(quota))
|
||||||
|
@ -84,27 +84,31 @@ describe('sandbox.run', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
describe('when given infinite loops', function()
|
if sandbox.quota_supported then
|
||||||
|
describe('when given infinite loops', function()
|
||||||
|
it('throws an error with infinite loops', function()
|
||||||
|
assert.error(function() sandbox.run("while true do end") end)
|
||||||
|
end)
|
||||||
|
|
||||||
it('throws an error with infinite loops', function()
|
it('restores string.rep even after a while true', function()
|
||||||
assert.error(function() sandbox.run("while true do end") end)
|
assert.error(function() sandbox.run("while true do end") end)
|
||||||
|
assert.equal('hellohello', string.rep('hello', 2))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('accepts a quota param', function()
|
||||||
|
assert.has_no.errors(function() sandbox.run("for i=1,100 do end") end)
|
||||||
|
assert.error(function() sandbox.run("for i=1,100 do end", {quota = 20}) end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('does not use quotes if the quote param is false', function()
|
||||||
|
assert.has_no.errors(function() sandbox.run("for i=1,1000000 do end", {quota = false}) end)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
else
|
||||||
it('restores string.rep even after a while true', function()
|
it('throws an error when trying to use the quota option in an unsupported environment (LuaJIT)', function()
|
||||||
assert.error(function() sandbox.run("while true do end") end)
|
assert.error(function() sandbox.run("", {quota = 20}) end)
|
||||||
assert.equal('hellohello', string.rep('hello', 2))
|
|
||||||
end)
|
end)
|
||||||
|
end
|
||||||
it('accepts a quota param', function()
|
|
||||||
assert.has_no.errors(function() sandbox.run("for i=1,100 do end") end)
|
|
||||||
assert.error(function() sandbox.run("for i=1,100 do end", {quota = 20}) end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('does not use quotes if the quote param is false', function()
|
|
||||||
assert.has_no.errors(function() sandbox.run("for i=1,1000000 do end", {quota = false}) end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
describe('when given an env option', function()
|
describe('when given an env option', function()
|
||||||
|
Loading…
Reference in New Issue
Block a user