commit 31bac65e685eb9cac8fa1fcfdbf079e42232e730 Author: kikito Date: Mon Sep 2 22:11:33 2013 +0200 initial version diff --git a/sandbox.lua b/sandbox.lua new file mode 100644 index 0000000..9fdece8 --- /dev/null +++ b/sandbox.lua @@ -0,0 +1,46 @@ +local BASE_ENV = {} + +([[ + assert ipairs next pairs pcall tonumber tostring unpack select type _VERSION xpcall + + string.byte string.char string.find string.format string.gmatch string.gsub + string.len string.lower string.match string.reverse string.sub string.upper + + table.insert table.maxn table.remove table.sort + + math.abs math.acos math.asin math.atan math.atan2 math.ceil math.cos + math.cosh math.deg math.exp math.foor math.fmod math.frexp math.huge + math.ldexp math.log math.log10 math.max math.min math.modf math.pi + math.pow math.rad math.random math.sin math.sinh math.sqrt math.tan + math.tanh + + os.clock os.difftime os.time +]]):gsub('%S+', function(id) + local package, method = id:match('([^%.]+)%.([^%.]+)') + if package then + BASE_ENV[package] = BASE_ENV[package] or {} + BASE_ENV[package][method] = _G[package][method] + else + BASE_ENV[id] = _G[id] + end +end) + +local string_rep = string.rep + + +local function run(f, options) + if type(f) == 'string' then f = loadstring(f) end + + string.rep = nil + setfenv(f, BASE_ENV) + local result = f() + + string.rep = string_rep + + return result +end + +local sandbox = { run = run } + + +return setmetatable(sandbox, {__call = function(_,f) return run(f) end}) diff --git a/spec/sandbox_spec.lua b/spec/sandbox_spec.lua new file mode 100644 index 0000000..1461478 --- /dev/null +++ b/spec/sandbox_spec.lua @@ -0,0 +1,38 @@ +local sandbox = require 'sandbox' + +describe('sandbox', function() + + it('can run harmless functions', function() + local r = sandbox(function() return 'hello' end) + assert.equal(r, 'hello') + end) + + it('can run harmless strings', function() + local r = sandbox("return 'hello'") + assert.equal(r, 'hello') + end) + + it('has access to safe methods', function() + assert.equal(10, sandbox("return tonumber('10')")) + assert.equal('HELLO', sandbox("return string.upper('hello')")) + assert.equal(1, sandbox("local a = {3,2,1}; table.sort(a); return a[1]")) + assert.equal(10, sandbox("return math.max(1,10)")) + end) + + it('does not allow access to not-safe stuff', function() + assert.has_error(function() sandbox('return setmetatable({}, {})') end) + assert.has_error(function() sandbox('return string.rep("hello", 5)') end) + end) + + it('does not allow pesky string:rep', function() + assert.has_error(function() sandbox('return ("hello"):rep(5)') end) + end) + + it('restores the value of string.rep', function() + sandbox("") + assert.equal('hellohello', string.rep('hello', 2)) + end) + + + +end)