fixes exploits with infinite loops and better sandbox code checks
This commit is contained in:
parent
374c1bed5c
commit
e75ba494c7
201
init.lua
201
init.lua
@ -10,7 +10,7 @@ basic_robot.maxdig = 1; -- how many digs allowed per execution, 0 = unlimited
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
basic_robot.version = "11/22a";
|
basic_robot.version = "11/26a";
|
||||||
|
|
||||||
|
|
||||||
basic_robot.data = {};
|
basic_robot.data = {};
|
||||||
@ -99,6 +99,28 @@ function getSandboxEnv (name)
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
listen_msg = function()
|
||||||
|
local msg = basic_robot.data[name].listen_msg;
|
||||||
|
local speaker = basic_robot.data[name].listen_speaker;
|
||||||
|
basic_robot.data[name].listen_msg = nil;
|
||||||
|
basic_robot.data[name].listen_speaker = nil;
|
||||||
|
return speaker,msg
|
||||||
|
end,
|
||||||
|
|
||||||
|
read_mail = function()
|
||||||
|
local mail = basic_robot.data[name].listen_mail;
|
||||||
|
local sender = basic_robot.data[name].listen_sender;
|
||||||
|
basic_robot.data[name].listen_mail = nil;
|
||||||
|
basic_robot.data[name].listen_sender = nil;
|
||||||
|
return sender,mail
|
||||||
|
end,
|
||||||
|
|
||||||
|
send_mail = function(target,mail)
|
||||||
|
if not basic_robot.data[target] then return false end
|
||||||
|
basic_robot.data[target].listen_mail = mail;
|
||||||
|
basic_robot.data[target].listen_sender = name;
|
||||||
|
end,
|
||||||
|
|
||||||
remove = function()
|
remove = function()
|
||||||
basic_robot.data[name].obj:remove();
|
basic_robot.data[name].obj:remove();
|
||||||
basic_robot.data[name].obj=nil;
|
basic_robot.data[name].obj=nil;
|
||||||
@ -111,6 +133,41 @@ function getSandboxEnv (name)
|
|||||||
basic_robot.data[name].allow_spam = nil
|
basic_robot.data[name].allow_spam = nil
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
fire = function(speed, pitch,gravity) -- experimental: fires an projectile
|
||||||
|
local obj = basic_robot.data[name].obj;
|
||||||
|
local pos = obj:getpos();
|
||||||
|
local yaw = obj:getyaw();
|
||||||
|
pitch = pitch*math.pi/180
|
||||||
|
local velocity = {x=speed*math.cos(yaw)*math.cos(pitch), y=speed*math.sin(pitch),z=speed*math.sin(yaw)*math.cos(pitch)};
|
||||||
|
-- fire particle
|
||||||
|
-- minetest.add_particle(
|
||||||
|
-- {
|
||||||
|
-- pos = pos,
|
||||||
|
-- expirationtime = 10,
|
||||||
|
-- velocity = {x=speed*math.cos(yaw)*math.cos(pitch), y=speed*math.sin(pitch),z=speed*math.sin(yaw)*math.cos(pitch)},
|
||||||
|
-- size = 5,
|
||||||
|
-- texture = "default_apple.png",
|
||||||
|
-- acceleration = {x=0,y=-gravity,z=0},
|
||||||
|
-- collisiondetection = true,
|
||||||
|
-- collision_removal = true,
|
||||||
|
-- }
|
||||||
|
--);
|
||||||
|
|
||||||
|
local obj = minetest.add_entity(pos, "basic_robot:projectile");
|
||||||
|
if not obj then return end
|
||||||
|
obj:setvelocity(velocity);
|
||||||
|
obj:setacceleration({x=0,y=-gravity,z=0});
|
||||||
|
local luaent = obj:get_luaentity();
|
||||||
|
luaent.owner = name;
|
||||||
|
|
||||||
|
end,
|
||||||
|
|
||||||
|
fire_pos = function()
|
||||||
|
local fire_pos = basic_robot.data[name].fire_pos;
|
||||||
|
basic_robot.data[name].fire_pos = nil;
|
||||||
|
return fire_pos
|
||||||
|
end,
|
||||||
},
|
},
|
||||||
|
|
||||||
find_nodes =
|
find_nodes =
|
||||||
@ -169,48 +226,6 @@ function getSandboxEnv (name)
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
listen_msg = function()
|
|
||||||
local msg = basic_robot.data[name].listen_msg;
|
|
||||||
local speaker = basic_robot.data[name].listen_speaker;
|
|
||||||
basic_robot.data[name].listen_msg = nil;
|
|
||||||
basic_robot.data[name].listen_speaker = nil;
|
|
||||||
return speaker,msg
|
|
||||||
end,
|
|
||||||
|
|
||||||
fire = function(speed, pitch,gravity) -- experimental: fires an projectile
|
|
||||||
local obj = basic_robot.data[name].obj;
|
|
||||||
local pos = obj:getpos();
|
|
||||||
local yaw = obj:getyaw();
|
|
||||||
pitch = pitch*math.pi/180
|
|
||||||
local velocity = {x=speed*math.cos(yaw)*math.cos(pitch), y=speed*math.sin(pitch),z=speed*math.sin(yaw)*math.cos(pitch)};
|
|
||||||
-- fire particle
|
|
||||||
-- minetest.add_particle(
|
|
||||||
-- {
|
|
||||||
-- pos = pos,
|
|
||||||
-- expirationtime = 10,
|
|
||||||
-- velocity = {x=speed*math.cos(yaw)*math.cos(pitch), y=speed*math.sin(pitch),z=speed*math.sin(yaw)*math.cos(pitch)},
|
|
||||||
-- size = 5,
|
|
||||||
-- texture = "default_apple.png",
|
|
||||||
-- acceleration = {x=0,y=-gravity,z=0},
|
|
||||||
-- collisiondetection = true,
|
|
||||||
-- collision_removal = true,
|
|
||||||
-- }
|
|
||||||
--);
|
|
||||||
|
|
||||||
local obj = minetest.add_entity(pos, "basic_robot:projectile");
|
|
||||||
if not obj then return end
|
|
||||||
obj:setvelocity(velocity);
|
|
||||||
obj:setacceleration({x=0,y=-gravity,z=0});
|
|
||||||
local luaent = obj:get_luaentity();
|
|
||||||
luaent.owner = name;
|
|
||||||
|
|
||||||
end,
|
|
||||||
|
|
||||||
fire_pos = function()
|
|
||||||
local fire_pos = basic_robot.data[name].fire_pos;
|
|
||||||
basic_robot.data[name].fire_pos = nil;
|
|
||||||
return fire_pos
|
|
||||||
end,
|
|
||||||
|
|
||||||
book = {
|
book = {
|
||||||
read = function(i)
|
read = function(i)
|
||||||
@ -248,7 +263,7 @@ function getSandboxEnv (name)
|
|||||||
local ScriptFunc, CompileError = loadstring( script )
|
local ScriptFunc, CompileError = loadstring( script )
|
||||||
if CompileError then
|
if CompileError then
|
||||||
minetest.chat_send_player(name, "#code.run: compile error " .. CompileError )
|
minetest.chat_send_player(name, "#code.run: compile error " .. CompileError )
|
||||||
return
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
setfenv( ScriptFunc, basic_robot.data[name].sandbox )
|
setfenv( ScriptFunc, basic_robot.data[name].sandbox )
|
||||||
@ -256,8 +271,9 @@ function getSandboxEnv (name)
|
|||||||
local Result, RuntimeError = pcall( ScriptFunc );
|
local Result, RuntimeError = pcall( ScriptFunc );
|
||||||
if RuntimeError then
|
if RuntimeError then
|
||||||
minetest.chat_send_player(name, "#code.run: run error " .. RuntimeError )
|
minetest.chat_send_player(name, "#code.run: run error " .. RuntimeError )
|
||||||
return
|
return false
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -325,7 +341,7 @@ end
|
|||||||
local function check_code(code)
|
local function check_code(code)
|
||||||
|
|
||||||
--"while ", "for ", "do ","goto ",
|
--"while ", "for ", "do ","goto ",
|
||||||
local bad_code = {"repeat ", "until ", "_ccounter"}
|
local bad_code = {"repeat ", "until ", "_ccounter", "_G", "while%(", "while{", "pcall"}
|
||||||
|
|
||||||
for _, v in pairs(bad_code) do
|
for _, v in pairs(bad_code) do
|
||||||
if string.find(code, v) then
|
if string.find(code, v) then
|
||||||
@ -335,6 +351,34 @@ local function check_code(code)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function is_inside_string(pos,script)
|
||||||
|
local i1=string.find (script, "\"", 1);
|
||||||
|
if not i1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local i2=0;
|
||||||
|
local par = 1;
|
||||||
|
|
||||||
|
if pos<i1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
while i1 do
|
||||||
|
i2=string.find(script,"\"",i1+1);
|
||||||
|
if i2 then
|
||||||
|
par = 1 - par;
|
||||||
|
end
|
||||||
|
if par == 0 then
|
||||||
|
if i1<pos and pos<i2 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
i1=i2;
|
||||||
|
end
|
||||||
|
return false;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local function CompileCode ( script )
|
local function CompileCode ( script )
|
||||||
|
|
||||||
--[[ idea: in each local a = function (args) ... end insert counter like:
|
--[[ idea: in each local a = function (args) ... end insert counter like:
|
||||||
@ -342,7 +386,9 @@ local function CompileCode ( script )
|
|||||||
when counter exceeds limit exit with error
|
when counter exceeds limit exit with error
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
|
|
||||||
script="_ccounter = 0; " .. script;
|
script="_ccounter = 0; " .. script;
|
||||||
|
|
||||||
local i1 -- process script to insert call counter in every function
|
local i1 -- process script to insert call counter in every function
|
||||||
local insert_code = " increase_ccounter(); ";
|
local insert_code = " increase_ccounter(); ";
|
||||||
|
|
||||||
@ -350,45 +396,56 @@ local function CompileCode ( script )
|
|||||||
|
|
||||||
while (i2) do -- PROCESS SCRIPT AND INSERT COUNTER AT PROBLEMATIC SPOTS
|
while (i2) do -- PROCESS SCRIPT AND INSERT COUNTER AT PROBLEMATIC SPOTS
|
||||||
i2 = nil;
|
i2 = nil;
|
||||||
|
|
||||||
i2=string.find (script, "function", i1) -- fix functions
|
i2=string.find (script, "function", i1) -- fix functions
|
||||||
|
|
||||||
if i2 then
|
if i2 then
|
||||||
i2=string.find(script, ")", i2);
|
if not is_inside_string(i2,script) then
|
||||||
if i2 then
|
i2=string.find(script, ")", i2);
|
||||||
script = script.sub(script,1, i2) .. insert_code .. script.sub(script, i2+1);
|
if i2 then
|
||||||
i1=i2+string.len(insert_code);
|
script = script.sub(script,1, i2) .. insert_code .. script.sub(script, i2+1);
|
||||||
|
i1=i2+string.len(insert_code);
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
i2=string.find (script, "for ", i1) -- fix for OK
|
i2=string.find (script, "for ", i1) -- fix for OK
|
||||||
if i2 then
|
if i2 then
|
||||||
i2=string.find(script, "do", i2);
|
if not is_inside_string(i2,script) then
|
||||||
if i2 then
|
i2=string.find(script, "do ", i2);
|
||||||
script = script.sub(script,1, i2+1) .. insert_code .. script.sub(script, i2+2);
|
if i2 then
|
||||||
i1=i2+string.len(insert_code);
|
script = script.sub(script,1, i2+1) .. insert_code .. script.sub(script, i2+2);
|
||||||
|
i1=i2+string.len(insert_code);
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
i2=string.find (script, "while ", i1) -- fix while OK
|
i2=string.find (script, "while ", i1) -- fix while OK
|
||||||
if i2 then
|
if i2 then
|
||||||
i2=string.find(script, "do", i2);
|
if not is_inside_string(i2,script) then
|
||||||
if i2 then
|
i2=string.find(script, "do ", i2);
|
||||||
script = script.sub(script,1, i2+1) .. insert_code .. script.sub(script, i2+2);
|
if i2 then
|
||||||
i1=i2+string.len(insert_code);
|
script = script.sub(script,1, i2+1) .. insert_code .. script.sub(script, i2+2);
|
||||||
|
i1=i2+string.len(insert_code);
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
i2=string.find (script, "goto ", i1) -- fix goto OK
|
i2=string.find (script, "goto ", i1) -- fix goto OK
|
||||||
|
|
||||||
if i2 then
|
if i2 then
|
||||||
script = script.sub(script,1, i2-1) .. insert_code .. script.sub(script, i2);
|
if not is_inside_string(i2,script) then
|
||||||
i1=i2+string.len(insert_code)+5; -- insert + skip goto
|
script = script.sub(script,1, i2-1) .. insert_code .. script.sub(script, i2);
|
||||||
|
i1=i2+string.len(insert_code)+5; -- insert + skip goto
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--minetest.chat_send_all(script)
|
||||||
|
--if true then return nil, "" end
|
||||||
|
|
||||||
local ScriptFunc, CompileError = loadstring( script )
|
local ScriptFunc, CompileError = loadstring( script )
|
||||||
if CompileError then
|
if CompileError then
|
||||||
return nil, CompileError
|
return nil, CompileError
|
||||||
@ -657,8 +714,9 @@ local spawn_robot = function(pos,node,ttl)
|
|||||||
|
|
||||||
-- if robot already exists do nothing
|
-- if robot already exists do nothing
|
||||||
if basic_robot.data[owner] and basic_robot.data[owner].obj then
|
if basic_robot.data[owner] and basic_robot.data[owner].obj then
|
||||||
minetest.chat_send_player(owner,"#ROBOT ERROR : robot already active")
|
minetest.chat_send_player(owner,"#ROBOT: robot already active, removing")
|
||||||
return
|
basic_robot.data[owner].obj:remove();
|
||||||
|
basic_robot.data[owner].obj = nil;
|
||||||
end
|
end
|
||||||
|
|
||||||
local obj = minetest.add_entity(pos,"basic_robot:robot");
|
local obj = minetest.add_entity(pos,"basic_robot:robot");
|
||||||
@ -721,14 +779,16 @@ local on_receive_robot_form = function(pos, formname, fields, sender)
|
|||||||
"**ROBOT\n"..
|
"**ROBOT\n"..
|
||||||
"say(\"hello\") will speak\n"..
|
"say(\"hello\") will speak\n"..
|
||||||
"self.listen(0/1) (de)attaches chat listener to robot\n"..
|
"self.listen(0/1) (de)attaches chat listener to robot\n"..
|
||||||
"speaker, msg = listen_msg() retrieves last chat message if robot listens\n"..
|
"speaker, msg = self.listen_msg() retrieves last chat message if robot listens\n"..
|
||||||
|
"self.send_mail(target,mail) sends mail to target robot\n"..
|
||||||
|
"sender,mail = read_mail() reads mail, if any\n" ..
|
||||||
"self.pos() returns table {x=pos.x,y=pos.y,z=pos.z}\n"..
|
"self.pos() returns table {x=pos.x,y=pos.y,z=pos.z}\n"..
|
||||||
"self.spam(0/1) (dis)enable message repeat to all\n"..
|
"self.spam(0/1) (dis)enable message repeat to all\n"..
|
||||||
"self.remove() removes robot\n"..
|
"self.remove() removes robot\n"..
|
||||||
"self.spawnpos() returns position of spawner block\n"..
|
"self.spawnpos() returns position of spawner block\n"..
|
||||||
"self.viewdir() returns vector of view for robot\n"..
|
"self.viewdir() returns vector of view for robot\n"..
|
||||||
"fire(speed, pitch,gravity) fires a projectile from robot\n"..
|
"self.fire(speed, pitch,gravity) fires a projectile from robot\n"..
|
||||||
"fire_pos() returns last hit position\n ";
|
"self.fire_pos() returns last hit position\n ";
|
||||||
|
|
||||||
text = minetest.formspec_escape(text);
|
text = minetest.formspec_escape(text);
|
||||||
|
|
||||||
@ -838,13 +898,15 @@ minetest.register_on_player_receive_fields(
|
|||||||
elseif fields.right then
|
elseif fields.right then
|
||||||
pcall(function () commands.move(name,2) end)
|
pcall(function () commands.move(name,2) end)
|
||||||
elseif fields.dig then
|
elseif fields.dig then
|
||||||
pcall(function () commands.dig(name,3) end)
|
pcall(function () basic_robot.data[name].digcount = 1; commands.dig(name,3) end)
|
||||||
elseif fields.up then
|
elseif fields.up then
|
||||||
pcall(function () commands.move(name,5) end)
|
pcall(function () commands.move(name,5) end)
|
||||||
elseif fields.down then
|
elseif fields.down then
|
||||||
pcall(function () commands.move(name,6) end)
|
pcall(function () commands.move(name,6) end)
|
||||||
elseif fields.digdown then
|
elseif fields.digdown then
|
||||||
pcall(function () commands.dig(name,6) end)
|
pcall(function () basic_robot.data[name].digcount = 1; commands.dig(name,6) end)
|
||||||
|
elseif fields.digup then
|
||||||
|
pcall(function () basic_robot.data[name].digcount = 1; commands.dig(name,5) end)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -936,7 +998,8 @@ local get_manual_control_form = function(name)
|
|||||||
"button[0.75,1.75;1.,1;back;BACK]"..
|
"button[0.75,1.75;1.,1;back;BACK]"..
|
||||||
"button[1.75,1.75;1.,1;up;UP]"..
|
"button[1.75,1.75;1.,1;up;UP]"..
|
||||||
|
|
||||||
"button[0.75,2.75;1.,1;digdown;DDown]";
|
"button[-0.25,2.65;1.,1;digdown;DDown]"..
|
||||||
|
"button[1.75,2.65;1.,1;digup;DUp]";
|
||||||
|
|
||||||
return form;
|
return form;
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user