|
@@ -266,32 +266,45 @@ local function remove_functions(x) |
|
|
return x |
|
|
end |
|
|
|
|
|
-- itbl: Flat table of functions to run after sandbox cleanup, used to prevent various security hazards |
|
|
local function get_interrupt(pos, itbl, send_warning) |
|
|
-- iid = interrupt id |
|
|
local function interrupt(time, iid) |
|
|
-- NOTE: This runs within string metatable sandbox, so don't *rely* on anything of the form (""):y |
|
|
-- Hence the values get moved out. Should take less time than original, so totally compatible |
|
|
if type(time) ~= "number" then return end |
|
|
table.insert(itbl, function () |
|
|
-- Outside string metatable sandbox, can safely run this now |
|
|
local luac_id = minetest.get_meta(pos):get_int("luac_id") |
|
|
-- Check if IID is dodgy, so you can't use interrupts to store an infinite amount of data. |
|
|
-- Note that this is safe from alter-after-free because this code gets run after the sandbox has ended. |
|
|
-- This runs outside of the timer and *shouldn't* harm perf. unless dodgy data is being sent in the first place |
|
|
iid = remove_functions(iid) |
|
|
local msg_ser = minetest.serialize(iid) |
|
|
if #msg_ser <= mesecon.setting("luacontroller_interruptid_maxlen", 256) then |
|
|
mesecon.queue:add_action(pos, "lc_interrupt", {luac_id, iid}, time, iid, 1) |
|
|
else |
|
|
send_warning("An interrupt ID was too large!") |
|
|
end |
|
|
-- The setting affects API so is not intended to be changeable at runtime |
|
|
local get_interrupt |
|
|
if mesecon.setting("luacontroller_lightweight_interrupts", false) then |
|
|
-- use node timer |
|
|
get_interrupt = function(pos, itbl, send_warning) |
|
|
return (function(time, iid) |
|
|
if type(time) ~= "number" then error("Delay must be a number") end |
|
|
if iid ~= nil then send_warning("Interrupt IDs are disabled on this server") end |
|
|
table.insert(itbl, function() minetest.get_node_timer(pos):start(time) end) |
|
|
end) |
|
|
end |
|
|
return interrupt |
|
|
else |
|
|
-- use global action queue |
|
|
-- itbl: Flat table of functions to run after sandbox cleanup, used to prevent various security hazards |
|
|
get_interrupt = function(pos, itbl, send_warning) |
|
|
-- iid = interrupt id |
|
|
local function interrupt(time, iid) |
|
|
-- NOTE: This runs within string metatable sandbox, so don't *rely* on anything of the form (""):y |
|
|
-- Hence the values get moved out. Should take less time than original, so totally compatible |
|
|
if type(time) ~= "number" then error("Delay must be a number") end |
|
|
table.insert(itbl, function () |
|
|
-- Outside string metatable sandbox, can safely run this now |
|
|
local luac_id = minetest.get_meta(pos):get_int("luac_id") |
|
|
-- Check if IID is dodgy, so you can't use interrupts to store an infinite amount of data. |
|
|
-- Note that this is safe from alter-after-free because this code gets run after the sandbox has ended. |
|
|
-- This runs outside of the timer and *shouldn't* harm perf. unless dodgy data is being sent in the first place |
|
|
iid = remove_functions(iid) |
|
|
local msg_ser = minetest.serialize(iid) |
|
|
if #msg_ser <= mesecon.setting("luacontroller_interruptid_maxlen", 256) then |
|
|
mesecon.queue:add_action(pos, "lc_interrupt", {luac_id, iid}, time, iid, 1) |
|
|
else |
|
|
send_warning("An interrupt ID was too large!") |
|
|
end |
|
|
end) |
|
|
end |
|
|
return interrupt |
|
|
end |
|
|
end |
|
|
|
|
|
|
|
|
-- Given a message object passed to digiline_send, clean it up into a form |
|
|
-- which is safe to transmit over the network and compute its "cost" (a very |
|
|
-- rough estimate of its memory usage). |
|
@@ -414,7 +427,6 @@ local function get_digiline_send(pos, itbl, send_warning) |
|
|
end |
|
|
end |
|
|
|
|
|
|
|
|
local safe_globals = { |
|
|
-- Don't add pcall/xpcall unless willing to deal with the consequences (unless very careful, incredibly likely to allow killing server indirectly) |
|
|
"assert", "error", "ipairs", "next", "pairs", "select", |
|
@@ -651,6 +663,14 @@ local function reset(pos) |
|
|
set_port_states(pos, {a=false, b=false, c=false, d=false}) |
|
|
end |
|
|
|
|
|
local function node_timer(pos) |
|
|
if minetest.registered_nodes[minetest.get_node(pos).name].is_burnt then |
|
|
return false |
|
|
end |
|
|
run(pos, {type="interrupt"}) |
|
|
return false |
|
|
end |
|
|
|
|
|
----------------------- |
|
|
-- A.Queue callbacks -- |
|
|
----------------------- |
|
@@ -823,6 +843,7 @@ for d = 0, 1 do |
|
|
mesecon.receptor_off(pos, output_rules) |
|
|
end, |
|
|
is_luacontroller = true, |
|
|
on_timer = node_timer, |
|
|
on_blast = mesecon.on_blastnode, |
|
|
}) |
|
|
end |
|
|