[solved] Sandbox Env doesn't Recognize Functions
In other words, when I try and run code in the sandbox, functions are undefined (or nil) causing the game to crash. Much of the code is based off that for the Mesecons Luacontroller, as that was the best I could find to help be understand how to use sandboxes to begin with. I'm not sure that the method I'm using is the best, as things are spread in between os.lua and api.lua. I was hoping to put everything there, but then the custom functions would be undefined when simply forming the env table. Anyways, here's what I came up with.
env table and custom functions (api.lua):
run code in environment (os.lua):
callback from formspec on_receive_fields (api.lua):
As you might notice, all the functions defined should mostly be defined right inside the on_receive_fields, as they need access to the meta data. However, when I did that I was bombarded with even more errors about undefined global functions from the env table. I really don't think I'm doing this the best way, so that's why I'm asking.
In case you wonder, this is for my mod, digicompute. It aims to introduce fully functional Lua computers. If you'd like to see the full code, it can be accessed here after Wednesday, October 12th (I'm away from home, and something is up with my server). In the meantime, I've pushed the code to GitHub (and may leave it that way, IDK). There is now Wiki, and the README is from digiterm (the mod was originally a fork, but there's nothing from digiterm left - completely redesigned), but I'm working on a new one. Below is the error log.
error log:
Thanks in advance.
env table and custom functions (api.lua):
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
- Code: Select all
-----------------
-- ENVIRONMENT --
-----------------
-- CUSTOM SAFE FUNCTIONS --
local function safe_print(param)
print(dump(param))
end
local function safe_date()
return(os.date("*t",os.time()))
end
-- string.rep(str, n) with a high value for n can be used to DoS
-- the server. Therefore, limit max. length of generated string.
local function safe_string_rep(str, n)
if #str * n > mesecon.setting("luacontroller_string_rep_max", 64000) then
debug.sethook() -- Clear hook
error("string.rep: string length overflow", 2)
end
return string.rep(str, n)
end
-- string.find with a pattern can be used to DoS the server.
-- Therefore, limit string.find to patternless matching.
local function safe_string_find(...)
if (select(4, ...)) ~= true then
debug.sethook() -- Clear hook
error("string.find: 'plain' (fourth parameter) must always be true for digicomputers.")
end
return string.find(...)
end
-- [function] set
local function set_string(key, value)
return meta:set_string(key, value)
end
-- [function] get
local function get_string(key)
return meta:get_string(key)
end
-- [function] set int
local function set_int(key, value)
return meta:set_int(key, value)
end
-- [function] get int
local function get_int(key)
return meta:get_int(key)
end
-- [function] set float
local function set_float(key, value)
return meta:set_float(key, value)
end
-- [function] get float
local function get_float(key)
return meta:get_float(key)
end
-- [function] get input
local function get_input()
return meta:get_string("input")
end
-- [function] set input
local function set_input(value)
return meta:set_string("input", value)
end
-- [function] get output
local function get_output()
return meta:get_string("output")
end
-- [function] set output
local function set_output(value)
return meta:set_string("output", value)
end
-- [function] get field
local function get_field(key)
return field[key]
end
-- [function] refresh formspec
local function refresh()
meta:set_string("formspec", digicompute.formspec(meta:get_string("input"), meta:get_string("output")))
end
-- env
local env = {
run = digicompute.os.run,
set_string = set_string,
get_string = get_string,
set_int = set_int,
get_int = get_int,
set_float = set_float,
get_float = get_float,
get_input = get_input,
set_input = set_input,
get_output = get_output,
set_output = set_output,
get_field = get_field,
refresh = refresh,
string = {
byte = string.byte,
char = string.char,
format = string.format,
len = string.len,
lower = string.lower,
upper = string.upper,
rep = safe_string_rep,
reverse = string.reverse,
sub = string.sub,
find = safe_string_find,
},
math = {
abs = math.abs,
acos = math.acos,
asin = math.asin,
atan = math.atan,
atan2 = math.atan2,
ceil = math.ceil,
cos = math.cos,
cosh = math.cosh,
deg = math.deg,
exp = math.exp,
floor = math.floor,
fmod = math.fmod,
frexp = math.frexp,
huge = math.huge,
ldexp = math.ldexp,
log = math.log,
log10 = math.log10,
max = math.max,
min = math.min,
modf = math.modf,
pi = math.pi,
pow = math.pow,
rad = math.rad,
random = math.random,
sin = math.sin,
sinh = math.sinh,
sqrt = math.sqrt,
tan = math.tan,
tanh = math.tanh,
},
table = {
concat = table.concat,
insert = table.insert,
maxn = table.maxn,
remove = table.remove,
sort = table.sort,
},
os = {
clock = os.clock,
difftime = os.difftime,
time = os.time,
datetable = safe_date,
},
}
run code in environment (os.lua):
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
- Code: Select all
-- [function] run code (in sandbox env)
function digicompute.os.run(f, env)
setfenv(f, env)
local e, msg = pcall(f)
if e == false then return msg end
end
-- [function] run file under env
function digicompute.os.runfile(pos, path, errloc)
local env = digicompute.create_env(pos)
local f = loadfile(path) -- load func
local e = digicompute.os.run(f, env) -- run func
-- if error, call error handle function and re-run start
if e then
digicompute.os.handle_error(pos, e, errloc) -- handle error
local s = loadfile(path.."/"..name.."/os/start.lua") -- load start func
digicompute.os.run(s, env) -- run func
end
end
callback from formspec on_receive_fields (api.lua):
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
- Code: Select all
digicompute.os.runfile(pos, path.."/"..name.."/os/main.lua", "main")
As you might notice, all the functions defined should mostly be defined right inside the on_receive_fields, as they need access to the meta data. However, when I did that I was bombarded with even more errors about undefined global functions from the env table. I really don't think I'm doing this the best way, so that's why I'm asking.
In case you wonder, this is for my mod, digicompute. It aims to introduce fully functional Lua computers. If you'd like to see the full code, it can be accessed here after Wednesday, October 12th (I'm away from home, and something is up with my server). In the meantime, I've pushed the code to GitHub (and may leave it that way, IDK). There is now Wiki, and the README is from digiterm (the mod was originally a fork, but there's nothing from digiterm left - completely redesigned), but I'm working on a new one. Below is the error log.
error log:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
- Code: Select all
2016-10-09 17:53:27: WARNING[Server]: Undeclared global variable "set_output" accessed at ...inetest/worlds/digicompute/digicompute/oct8/os/start.lua:1
2016-10-09 17:53:27: WARNING[Server]: Undeclared global variable "get_string" accessed at ...inetest/worlds/digicompute/digicompute/oct8/os/start.lua:1
2016-10-09 17:53:27: ERROR[Main]: ServerError: Lua: Runtime error from mod 'digicompute' in callback node_on_receive_fields(): ...inetest/worlds/digicompute/digicompute/oct8/os/start.lua:1: attempt to call global 'get_string' (a nil value)
2016-10-09 17:53:27: ERROR[Main]: stack traceback:
2016-10-09 17:53:27: ERROR[Main]: ...inetest/worlds/digicompute/digicompute/oct8/os/start.lua:1: in main chunk
2016-10-09 17:53:27: ERROR[Main]: [C]: in function 'dofile'
2016-10-09 17:53:27: ERROR[Main]: ...inetest/worlds/digicompute/worldmods/digicompute/api.lua:308: in function <...inetest/worlds/digicompute/worldmods/digicompute/api.lua:295>
Thanks in advance.