techpack/safer_lua/environ.lua
2018-06-25 20:42:47 +02:00

118 lines
2.3 KiB
Lua

--[[
SaferLua [safer_lua]
====================
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
environ.lua:
]]--
safer_lua.MaxCodeSize = 1000 -- size in length of byte code
safer_lua.MaxTableSize = 1000 -- number of table entries considering string lenghts
local BASE_ENV = {
Store = safer_lua.Store,
math = {
floor = math.floor,
abs = math.abs,
max = math.max,
min = math.min,
random = math.random,
},
tonumber = tonumber,
tostring = tostring,
type = type,
ticks = 0,
}
local function map(dest, source)
for k,v in pairs(source) do
dest[k] = v
end
return dest
end
function safer_lua.config(max_code_size, max_table_size)
safer_lua.MaxCodeSize = max_code_size
safer_lua.MaxTableSize = max_table_size
end
local function compile(pos, text, label, err_clbk)
if safer_lua:check(text, label, err_clbk) == 0 then
text = text:gsub("%$", "S:")
local code, err = loadstring(text)
if not code then
err = err:gsub("%[string .+%]:", label)
err_clbk(pos, err)
else
return code
end
end
end
function safer_lua.init(pos, init, loop, environ, err_clbk)
if #init > safer_lua.MaxCodeSize then
err_clbk(pos, "init() Code size limit exceeded")
return
end
if #loop > safer_lua.MaxCodeSize then
err_clbk(pos, "loop() Code size limit exceeded")
return
end
local code = compile(pos, init, "init() ", err_clbk)
if code then
local env = BASE_ENV
env.S = {}
env.S = map(env.S, environ)
setfenv(code, env)
local res, err = pcall(code)
if not res then
err = err:gsub("%[string .+%]:", "init() ")
err_clbk(pos, err)
else
env = getfenv(code)
code = compile(pos, loop, "loop() ", err_clbk)
if code then
setfenv(code, env)
return code
end
end
end
end
function safer_lua.run_loop(pos, elapsed, code, err_clbk)
local env = getfenv(code)
env.event = false
env.ticks = env.ticks + 1
env.elapsed = elapsed
local res, err = pcall(code)
if not res then
err = err:gsub("%[string .+%]:", "loop() ")
err_clbk(pos, err)
return false
end
return true
end
function safer_lua.run_event(pos, code, err_clbk)
local env = getfenv(code)
env.event = true
env.elapsed = 0
local res, err = pcall(code)
if not res then
err = err:gsub("%[string .+%]:", "loop() ")
err_clbk(pos, err)
return false
end
return true
end