Wrap global variables created by sandbox so that they don't pollute the actual global sandbox table
This commit is contained in:
parent
12d7465f4e
commit
1c2111e266
@ -2,18 +2,11 @@
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
-- Copyright 2014 Perttu Ahola <celeron55@gmail.com>
|
||||
local log = buildat.Logger("__client/sandbox")
|
||||
local dump = buildat.dump
|
||||
|
||||
local buildat_safe_list = {
|
||||
"bytes",
|
||||
"dump",
|
||||
"Logger",
|
||||
}
|
||||
|
||||
local buildat_safe = {}
|
||||
|
||||
for _, name in ipairs(buildat_safe_list) do
|
||||
buildat_safe[name] = buildat[name]
|
||||
end
|
||||
--
|
||||
-- Base sandbox environment
|
||||
--
|
||||
|
||||
__buildat_sandbox_environment = {
|
||||
assert = assert, -- Safe according to http://lua-users.org/wiki/SandBoxes
|
||||
@ -48,7 +41,9 @@ __buildat_sandbox_environment = {
|
||||
os = { clock = os.clock, difftime = os.difftime, time = os.time },
|
||||
}
|
||||
|
||||
__buildat_sandbox_environment.buildat = buildat
|
||||
--
|
||||
-- Sandbox require
|
||||
--
|
||||
|
||||
__buildat_sandbox_environment.require = function(name)
|
||||
log:info("require(\""..name.."\")")
|
||||
@ -78,7 +73,45 @@ __buildat_sandbox_environment.require = function(name)
|
||||
error("require: \""..name.."\" not found in sandbox")
|
||||
end
|
||||
|
||||
--
|
||||
-- Running code in sandbox
|
||||
--
|
||||
|
||||
local function wrap_globals(base_sandbox)
|
||||
local sandbox = {}
|
||||
local sandbox_declared_globals = {}
|
||||
setmetatable(sandbox, {
|
||||
__index = function(t, k)
|
||||
local v = rawget(sandbox, k)
|
||||
if v ~= nil then return v end
|
||||
return base_sandbox[k]
|
||||
end,
|
||||
__newindex = function(t, k, v)
|
||||
if not sandbox_declared_globals[k] then
|
||||
local info = debug.getinfo(2, "Sl")
|
||||
log:info("sandbox["..dump(k).."] set by what="..dump(info.what)..
|
||||
", name="..dump(info.name))
|
||||
if info.what == "Lua" then
|
||||
error("Assignment to undeclared global \""..k.."\"\n in "..
|
||||
info.short_src.." line "..info.currentline)
|
||||
end
|
||||
end
|
||||
sandbox_declared_globals[k] = true
|
||||
rawset(sandbox, k, v)
|
||||
end
|
||||
})
|
||||
function sandbox.buildat.make_global(t)
|
||||
for k, v in pairs(t) do
|
||||
if sandbox[k] == nil then
|
||||
rawset(sandbox, k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
return sandbox
|
||||
end
|
||||
|
||||
local function run_function_in_sandbox(untrusted_function, sandbox)
|
||||
sandbox = wrap_globals(sandbox)
|
||||
setfenv(untrusted_function, sandbox)
|
||||
return __buildat_pcall(untrusted_function)
|
||||
end
|
||||
@ -108,6 +141,7 @@ function __buildat_run_code_in_sandbox(untrusted_code)
|
||||
return true
|
||||
end
|
||||
|
||||
-- TODO: : -> .
|
||||
function buildat:run_script_file(name)
|
||||
local code = __buildat_get_file_content(name)
|
||||
if not code then
|
||||
@ -118,4 +152,22 @@ function buildat:run_script_file(name)
|
||||
return __buildat_run_code_in_sandbox(code)
|
||||
end
|
||||
|
||||
--
|
||||
-- buildat namespace whitelist
|
||||
--
|
||||
|
||||
-- Whitelist the buildat namespace into the sandbox
|
||||
local buildat_safe_list = {
|
||||
"bytes",
|
||||
"dump",
|
||||
"Logger",
|
||||
"run_script_file",
|
||||
"sub_packet",
|
||||
"send_packet",
|
||||
}
|
||||
__buildat_sandbox_environment.buildat = {}
|
||||
for _, name in ipairs(buildat_safe_list) do
|
||||
__buildat_sandbox_environment.buildat[name] = buildat[name]
|
||||
end
|
||||
|
||||
log:info("sandbox.lua loaded")
|
||||
|
@ -51,16 +51,17 @@ local sandbox_function_name_to_global_function_name = {}
|
||||
local next_global_function_i = 1
|
||||
|
||||
function M.safe.SubscribeToEvent(event_name, function_name)
|
||||
if type(__buildat_sandbox_environment[function_name]) ~= 'function' then
|
||||
local caller_environment = getfenv(2)
|
||||
local callback = caller_environment[function_name]
|
||||
if type(callback) ~= 'function' then
|
||||
error("SubscribeToEvent(): '"..function_name..
|
||||
"' is not a global function in sandbox environment")
|
||||
"' is not a global function in current sandbox environment")
|
||||
end
|
||||
local global_function_i = next_global_function_i
|
||||
next_global_function_i = next_global_function_i + 1
|
||||
local global_function_name = "__buildat_sandbox_callback_"..global_function_i
|
||||
sandbox_function_name_to_global_function_name[function_name] = global_function_name
|
||||
_G[global_function_name] = function(eventType, eventData)
|
||||
local callback = __buildat_sandbox_environment[function_name]
|
||||
local f = function()
|
||||
callback(eventType, eventData)
|
||||
end
|
||||
|
@ -318,7 +318,7 @@ struct CApp: public App, public u3d::Application
|
||||
r == LUA_ERRMEM ? "ran out of memory" :
|
||||
r == LUA_ERRERR ? "error handler failed" : "unknown error";
|
||||
//log_e(MODULE, "Lua %s: %s", msg, cs(traceback));
|
||||
throw Exception(ss_()+"Lua "+msg+": "+traceback);
|
||||
throw Exception(ss_()+"Lua "+msg+":\n"+traceback);
|
||||
}
|
||||
//log_d(MODULE, "stack 4: %s", cs(dump_stack(L)));
|
||||
}
|
||||
|
@ -3,48 +3,47 @@
|
||||
-- Copyright 2014 Perttu Ahola <celeron55@gmail.com>
|
||||
local log = buildat.Logger("test1")
|
||||
local dump = buildat.dump
|
||||
local u3d = require("buildat/extension/urho3d")
|
||||
local cereal = require("buildat/extension/cereal")
|
||||
buildat.make_global(require("buildat/extension/urho3d"))
|
||||
log:info("test1/init.lua loaded")
|
||||
|
||||
-- 3D things
|
||||
|
||||
-- NOTE: Create global variable so that it doesn't get automatically deleted
|
||||
scene_ = u3d.Scene()
|
||||
scene_ = Scene()
|
||||
scene_:CreateComponent("Octree")
|
||||
|
||||
-- Note that naming the scene nodes is optional
|
||||
local plane_node = scene_:CreateChild("Plane")
|
||||
plane_node.scale = u3d.Vector3(10.0, 1.0, 10.0)
|
||||
plane_node.scale = Vector3(10.0, 1.0, 10.0)
|
||||
local plane_object = plane_node:CreateComponent("StaticModel")
|
||||
plane_object.model = u3d.cache:GetResource("Model", "Models/Plane.mdl")
|
||||
plane_object.material = u3d.cache:GetResource("Material", "Materials/StoneTiled.xml")
|
||||
plane_object.model = cache:GetResource("Model", "Models/Plane.mdl")
|
||||
plane_object.material = cache:GetResource("Material", "Materials/StoneTiled.xml")
|
||||
|
||||
local light_node = scene_:CreateChild("DirectionalLight")
|
||||
light_node.direction = u3d.Vector3(0.6, -1.0, 0.8) -- The direction vector does not need to be normalized
|
||||
light_node.direction = Vector3(0.6, -1.0, 0.8) -- The direction vector does not need to be normalized
|
||||
local light = light_node:CreateComponent("Light")
|
||||
light.lightType = u3d.LIGHT_DIRECTIONAL
|
||||
light.lightType = LIGHT_DIRECTIONAL
|
||||
|
||||
-- Add a camera so we can look at the scene
|
||||
camera_node = scene_:CreateChild("Camera")
|
||||
camera_node:CreateComponent("Camera")
|
||||
camera_node.position = u3d.Vector3(7.0, 7.0, 7.0)
|
||||
camera_node.position = Vector3(7.0, 7.0, 7.0)
|
||||
--camera_node.rotation = Quaternion(0, 0, 0.0)
|
||||
camera_node:LookAt(u3d.Vector3(0, 1, 0))
|
||||
camera_node:LookAt(Vector3(0, 1, 0))
|
||||
-- And this thing so the camera is shown on the screen
|
||||
local viewport = u3d.Viewport:new(scene_, camera_node:GetComponent("Camera"))
|
||||
u3d.renderer:SetViewport(0, viewport)
|
||||
local viewport = Viewport:new(scene_, camera_node:GetComponent("Camera"))
|
||||
renderer:SetViewport(0, viewport)
|
||||
|
||||
-- Add some text
|
||||
local title_text = u3d.ui.root:CreateChild("Text")
|
||||
local title_text = ui.root:CreateChild("Text")
|
||||
title_text:SetText("test1/init.lua")
|
||||
title_text:SetFont(u3d.cache:GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15)
|
||||
title_text.horizontalAlignment = u3d.HA_CENTER
|
||||
title_text.verticalAlignment = u3d.VA_CENTER
|
||||
title_text:SetPosition(0, u3d.ui.root.height*(-0.33))
|
||||
title_text:SetFont(cache:GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15)
|
||||
title_text.horizontalAlignment = HA_CENTER
|
||||
title_text.verticalAlignment = VA_CENTER
|
||||
title_text:SetPosition(0, ui.root.height*(-0.33))
|
||||
|
||||
local cereal = require("buildat/extension/cereal")
|
||||
|
||||
local the_box = nil
|
||||
the_box = nil
|
||||
|
||||
buildat.sub_packet("test1:add_box", function(data)
|
||||
local values = cereal.binary_input(data, {"object",
|
||||
@ -70,31 +69,31 @@ buildat.sub_packet("test1:add_box", function(data)
|
||||
-- 1) Make the entity in the scene
|
||||
local node = scene_:CreateChild("THE GLORIOUS BOX")
|
||||
the_box = node
|
||||
node.scale = u3d.Vector3(w, h, d)
|
||||
node.position = u3d.Vector3(x, y, z)
|
||||
node.scale = Vector3(w, h, d)
|
||||
node.position = Vector3(x, y, z)
|
||||
|
||||
-- 2) Create a StaticModel which kind of is what we need
|
||||
local object = node:CreateComponent("StaticModel")
|
||||
|
||||
-- 3) First it needs a model. We could just load this binaray blob:
|
||||
object.model = u3d.cache:GetResource("Model", "Models/Box.mdl")
|
||||
object.model = cache:GetResource("Model", "Models/Box.mdl")
|
||||
-- TODO: let's not. Let's generate some geometry!
|
||||
--[[local cc = u3d.CustomGeometry()
|
||||
--[[local cc = CustomGeometry()
|
||||
cc.SetNumGeometries(1)
|
||||
cc.BeginGeometry(0, u3d.TRIANGLE_STRIP)
|
||||
cc.BeginGeometry(0, TRIANGLE_STRIP)
|
||||
cc.DefineVertex(]]
|
||||
|
||||
-- 4) Create a material. Again we could just load it from a file:
|
||||
--object.material = u3d.cache:GetResource("Material", "Materials/Stone.xml")
|
||||
--object.material = cache:GetResource("Material", "Materials/Stone.xml")
|
||||
-- ...but let's create a material ourselves:
|
||||
g_m = u3d.Material() -- It has to be global because deletion causes a crash
|
||||
object.material = g_m
|
||||
-- Call buildat.store_inifnitely() because deletion of it causes a crash
|
||||
object.material = Material:new()
|
||||
-- We use this Diff.xml file to define that we want diffuse rendering. It
|
||||
-- doesn't make much sense to define it ourselves as it consists of quite many
|
||||
-- parameters:
|
||||
object.material:SetTechnique(0, u3d.cache:GetResource("Technique", "Techniques/Diff.xml"))
|
||||
object.material:SetTechnique(0, cache:GetResource("Technique", "Techniques/Diff.xml"))
|
||||
-- And load the texture from a file:
|
||||
object.material:SetTexture(u3d.TU_DIFFUSE, u3d.cache:GetResource("Texture2D", "Textures/LogoLarge.png"))
|
||||
object.material:SetTexture(TU_DIFFUSE, cache:GetResource("Texture2D", "Textures/LogoLarge.png"))
|
||||
|
||||
--
|
||||
-- Make a non-useful but nice reply packet and send it to the server
|
||||
@ -137,7 +136,7 @@ end)
|
||||
|
||||
function move_box_by_user_input(dt)
|
||||
-- Do not move if the UI has a focused element (the console)
|
||||
if u3d.ui.focusElement ~= nil then
|
||||
if ui.focusElement ~= nil then
|
||||
return
|
||||
end
|
||||
|
||||
@ -146,21 +145,21 @@ function move_box_by_user_input(dt)
|
||||
|
||||
if the_box then
|
||||
local p = the_box.position
|
||||
p.y = u3d.Clamp(p.y - u3d.input.mouseMove.y * MOUSE_SENSITIVITY, 0, 5)
|
||||
p.y = Clamp(p.y - input.mouseMove.y * MOUSE_SENSITIVITY, 0, 5)
|
||||
the_box.position = p -- Needed?
|
||||
end
|
||||
|
||||
if u3d.input:GetKeyDown(u3d.KEY_W) then
|
||||
the_box:Translate(u3d.Vector3(-1.0, 0.0, 0.0) * MOVE_SPEED * dt)
|
||||
if input:GetKeyDown(KEY_W) then
|
||||
the_box:Translate(Vector3(-1.0, 0.0, 0.0) * MOVE_SPEED * dt)
|
||||
end
|
||||
if u3d.input:GetKeyDown(u3d.KEY_S) then
|
||||
the_box:Translate(u3d.Vector3(1.0, 0.0, 0.0) * MOVE_SPEED * dt)
|
||||
if input:GetKeyDown(KEY_S) then
|
||||
the_box:Translate(Vector3(1.0, 0.0, 0.0) * MOVE_SPEED * dt)
|
||||
end
|
||||
if u3d.input:GetKeyDown(u3d.KEY_A) then
|
||||
the_box:Translate(u3d.Vector3(0.0, 0.0, -1.0) * MOVE_SPEED * dt)
|
||||
if input:GetKeyDown(KEY_A) then
|
||||
the_box:Translate(Vector3(0.0, 0.0, -1.0) * MOVE_SPEED * dt)
|
||||
end
|
||||
if u3d.input:GetKeyDown(u3d.KEY_D) then
|
||||
the_box:Translate(u3d.Vector3(0.0, 0.0, 1.0) * MOVE_SPEED * dt)
|
||||
if input:GetKeyDown(KEY_D) then
|
||||
the_box:Translate(Vector3(0.0, 0.0, 1.0) * MOVE_SPEED * dt)
|
||||
end
|
||||
end
|
||||
|
||||
@ -170,5 +169,5 @@ function handle_update(eventType, eventData)
|
||||
--node:Rotate(Quaternion(50, 80*dt, 0, 0))
|
||||
move_box_by_user_input(dt)
|
||||
end
|
||||
u3d.SubscribeToEvent("Update", "handle_update")
|
||||
SubscribeToEvent("Update", "handle_update")
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user