-- example/simple-example.lua -- -- Sandbox (for) Untrusted Procedure Partitioning (in) Lua Engine -- -- Simple example -- -- Copyright 2012 Daniel Silverstone -- -- For licence terms, see COPYING -- supple = require'supple' -- Code string to run in the untrusted environment subcode = [[ local t = ... local tot = 0 for i = 1, #t do tot = tot + t[i]() end t.tot = tot return tot, -t ]] -- Generate a function to return 'n' local function give_n(n) return function() return n end end -- A useful table for the test local tab = { give_n(4), give_n(8), give_n(12), } -- A metatable which defines -tab to equal 'JEFF' local mt = { __unm = function () return "JEFF" end } setmetatable(tab, mt) local function lprint(...) local foo = {n=select("#",...),...} if foo[1] then print "Function ran OK:" else print "Error encountered:" end for i = 2, foo.n do if type(foo[i]) == "table" then print("{") for k, v in pairs(foo[i]) do print("",k,v) end print("}") else print(foo[i]) end end print() end -- Finally, run the subcode lprint(supple.host.run(subcode, "@test-code", tab)) assert(tab.tot == 24) -- Now run a supple command which we expect to error out. lprint(supple.host.run("unknown()", "@test-code")) -- And now, one where we pass an error from host to sandbox and back lprint(supple.host.run("local f = ... f()", "@test-code", function() unknown() end)) -- And now, one where we pass an error from sandbox to host to sandbox and back lprint(supple.host.run("local f = ... f(function() unknown() end)", "@test-code", function(ff) ff() end)) -- Next , a reasonable traceback via named functions on each end... local errsrc = [[ function raises() does_not_exist() end function passes() raises() end function chains(f) f(passes) end local callme = ... callme(chains) ]] function loopback(f) f(loopback) end lprint(supple.host.run(errsrc, "@error-code", loopback)) -- Now we try the sandboxing limits local long_run = [[ local s = "" for i = 1, 10000 do s = s .. "FISHFISHFISHFISHFISH" end return #s ]] supple.host.set_limits { count = 100 } lprint(supple.host.run(long_run, "@long-code")) supple.host.set_limits { memory = 1000 } lprint(supple.host.run(long_run, "@big-code")) -- next we demonstrate that ipairs works on proxied tables local summing = [[ local t = ... local tot = 0 for i, v in ipairs(t) do tot = tot + v end return tot ]] lprint(supple.host.run(summing, "@summing", { 10, 14, 3 })) -- next we demonstrate that next works on proxied tables local isempty = [[ local t = ... return next(t) == nil ]] lprint(supple.host.run(isempty, "@isempty", {})) lprint(supple.host.run(isempty, "@isempty", {"bar"})) -- And now that pairs works on proxied tables local keys = [[ local t = ... local ret = {} for k, v in pairs(t) do ret[#ret+1] = k end ret.ret = ret return ret ]] lprint(supple.host.run(keys, "@keys", { foo="bar", baz="meta" }))