first commit

master
Joachim Stolberg 2020-03-14 23:08:06 +01:00
commit 1c4a388a1f
12 changed files with 1156 additions and 0 deletions

364
data_struct.lua Normal file
View File

@ -0,0 +1,364 @@
--[[
SaferLua [safer_lua]
====================
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
data_struct.lua:
see https://github.com/joe7575/techpack/wiki/Data-Structures
]]--
safer_lua.DataStructHelp = [[
Data structures as a secure shell over the LUA table type.
see https://github.com/joe7575/techpack/wiki/Data-Structures
'Arrays' are lists of elements, which can be addressed
by means of an index:
a = Array(1,2,3,4) --> {1,2,3,4}
a.add(6) --> {1,2,3,4,6}
a.set(2, 8) --> {1,8,3,4,6}
a.insert(5,7) --> {1,8,3,4,7,6}
a.remove(3) --> {1,8,4,7,6}
a.insert(1, "hello") --> {"hello",1,8,4,7,6}
a.size() --> function returns 6
a.memsize() --> return returns 10
a.next() --> for loop iterator function
a.sort(reverse) --> sort the array elements in place
Unlike arrays, which are indexed by a range of numbers,
'stores' are indexed by keys:
s = Store("a",4,"b",5) --> {a = 4, b = 5}
s.set("val", 12) --> {a = 4, b = 5, val = 12}
s.get("val") --> returns 12
s.set(0, "hello") --> {a = 4, b = 5, val = 12, [0] = "hello"}
s.del("val") --> {[0] = "hello"}
s.size() --> function returns 4
s.memsize() --> function returns 8
s.next() --> for loop iterator function
s.keys(order) --> return an array with the keys
A 'set' is an unordered collection with no duplicate
elements.
s = Set("Tom", "Lucy")
--> {Tom = true, Lucy = true}
s.del("Tom") --> {Lucy = true}
s.add("Susi") --> {Lucy = true, Susi = true}
s.has("Susi") --> function returns `true`
s.has("Mike") --> function returns `false`
s.size() --> function returns 2
s.memsize() --> function returns 8
s.next() --> for loop iterator function
]]
local function var_count(v)
if type(v) == "number" then
return 1
elseif type(v) == "boolean" then
return 1
elseif v == nil then
return 0
elseif type(v) == "string" then
return #v
elseif type(v) == "table" then
return v.memsize()
else
return nil
end
end
function safer_lua.Store(...)
local new_t = {}
local mt = {}
local MemSize = 0
local Size = 0
local Data = {}
mt.__newindex = function(t, k, v) return end
mt.count = var_count
new_t.set = function(k,v)
if type(k) == "number" then
if rawget(Data, k) then -- has entry?
MemSize = MemSize - mt.count(rawget(Data, k))
else
Size = Size + 1
end
MemSize = MemSize + mt.count(v)
rawset(Data, k, v)
elseif type(k) == "string" then
if rawget(Data, k) then -- has entry?
MemSize = MemSize - mt.count(rawget(Data, k))
else
MemSize = MemSize + mt.count(k)
Size = Size + 1
end
MemSize = MemSize + mt.count(v)
rawset(Data, k, v)
end
end
new_t.get = function(k)
return rawget(Data, k)
end
new_t.del = function(k)
if rawget(Data, k) then -- has entry?
MemSize = MemSize - mt.count(k)
MemSize = MemSize - mt.count(rawget(Data, k))
rawset(Data, k, nil)
Size = Size - 1
end
end
new_t.memsize = function(t)
return MemSize
end
new_t.size = function(t)
return Size
end
new_t.next = function(t)
local n = nil
return function ()
n = next(Data, n)
if n then return n, Data[n] end
end
end
new_t.keys = function(order)
local keyset = {}
local n = 0
local size = 0
for k,v in pairs(Data) do
n = n + 1
keyset[n] = k
size = size + var_count(k)
end
if order == "up" then
table.sort(keyset, function(a,b) return a > b end)
elseif order == "down" then
table.sort(keyset)
end
local a = safer_lua.Array()
a.__load(size, keyset)
return a
end
new_t.__dump = function()
-- remove the not serializable meta data
return {Type = "Store", Size = Size, MemSize = MemSize, Data = Data}
end
new_t.__load = function(size, memsize, data)
Size = size
MemSize = memsize
Data = data
end
for idx = 1,select('#',...),2 do
local k,v = select(idx,...),select(idx+1,...)
new_t.set(k,v)
end
return setmetatable(new_t, mt)
end
function safer_lua.Array(...)
local new_t = {}
local mt = {}
local MemSize = 0
local Data = {}
mt.__newindex = function(t, k, v) return end
mt.count = var_count
for idx = 1,select('#',...) do
local v = select(idx,...)
local cnt = mt.count(v)
if cnt then
MemSize = MemSize + cnt
rawset(Data, idx, v)
end
end
new_t.add = function(v)
MemSize = MemSize + mt.count(v)
local i = #Data + 1
table.insert(Data, i, v)
end
new_t.set = function(i,v)
i = math.min(#Data, i)
MemSize = MemSize - mt.count(rawget(Data, i))
MemSize = MemSize + mt.count(v)
rawset(Data, i, v)
end
new_t.get = function(i)
return Data[i]
end
new_t.insert = function(i, v)
MemSize = MemSize + mt.count(v)
i = math.min(#Data, i)
table.insert(Data, i, v)
end
new_t.remove = function(i)
local v = table.remove(Data, i)
MemSize = MemSize - mt.count(v)
return v
end
new_t.sort = function(reverse)
if reverse then
table.sort(Data, function(a,b) return a > b end)
else
table.sort(Data)
end
end
new_t.memsize = function(t)
return MemSize
end
new_t.size = function(t)
return #Data
end
new_t.next = function(t)
local i = 0
local n = #Data
return function ()
i = i + 1
if i <= n then return i, Data[i] end
end
end
new_t.__dump = function()
-- remove the not serializable meta data
return {Type = "Array", MemSize = MemSize, Data = Data}
end
new_t.__load = function(memsize, data)
MemSize = memsize
Data = data
end
return setmetatable(new_t, mt)
end
function safer_lua.Set(...)
local new_t = {}
local mt = {}
local MemSize = 0
local Size = 0
local Data = {}
mt.__newindex = function(t, k, v) return end
mt.count = var_count
for idx = 1,select('#',...) do
local v = select(idx,...)
local cnt = mt.count(v)
if cnt then
MemSize = MemSize + cnt
Size = Size + 1
rawset(Data, v, true)
end
end
new_t.add = function(k)
MemSize = MemSize + mt.count(k)
rawset(Data, k, true)
Size = Size + 1
end
new_t.del = function(k)
MemSize = MemSize - mt.count(k)
rawset(Data, k, nil)
Size = Size - 1
end
new_t.has = function(k)
return rawget(Data, k) == true
end
new_t.memsize = function(t)
return MemSize
end
new_t.size = function(t)
return Size
end
new_t.next = function(t)
local i = 0
local n = nil
return function ()
i = i + 1
n = next(Data, n)
if n then return i, n end
end
end
new_t.__dump = function()
-- remove the not serializable meta data
return {Type = "Set", Size = Size, MemSize = MemSize, Data = Data}
end
new_t.__load = function(size, memsize, data)
Size = size
MemSize = memsize
Data = data
end
return setmetatable(new_t, mt)
end
-- remove the not serializable meta data
function safer_lua.datastruct_to_table(ds)
return ds.__dump()
end
-- add the not serializable meta data again
function safer_lua.table_to_datastruct(tbl)
if tbl.Type == "Store" then
local s = safer_lua.Store()
s.__load(tbl.Size, tbl.MemSize, tbl.Data)
return s
elseif tbl.Type == "Set" then
local s = safer_lua.Set()
s.__load(tbl.Size, tbl.MemSize, tbl.Data)
return s
elseif tbl.Type == "Array" then
local a = safer_lua.Array()
a.__load(tbl.MemSize, tbl.Data)
return a
end
end

0
depends.txt Normal file
View File

4
description.txt Normal file
View File

@ -0,0 +1,4 @@
SaferLua [safer_lua], a subset of the language Lua for safe and secure Lua sandboxes

211
environ.lua Normal file
View File

@ -0,0 +1,211 @@
--[[
SaferLua [safer_lua]
====================
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
environ.lua:
]]--
safer_lua.MaxCodeSize = 5000 -- size if source code in bytes
safer_lua.MaxTableSize = 1000 -- sum over all table sizes
safer_lua.MaxExeTime = 5000 -- max. execution time in us
local function memsize()
return safer_lua.MaxTableSize
end
local function range(from, to)
return function(expired_at,last)
assert(expired_at > minetest.get_us_time(), "Runtime limit exceeded")
if last >= to then
return nil
else
return last+1
end
end, minetest.get_us_time() + safer_lua.MaxExeTime, from-1
end
local BASE_ENV = {
Array = safer_lua.Array,
Store = safer_lua.Store,
Set = safer_lua.Set,
memsize = memsize,
range = range,
math = {
floor = math.floor,
abs = math.abs,
max = math.max,
min = math.min,
random = math.random,
},
string = {
byte = string.byte,
char = string.char,
find = string.find,
format = string.format,
gmatch = string.gmatch,
gsub = string.gsub,
len = string.len,
lower = string.lower,
match = string.match,
rep = string.rep,
sub = string.sub,
upper = string.upper,
split = string.split,
trim = string.trim,
},
tonumber = tonumber,
tostring = tostring,
unpack = unpack,
type = type,
ticks = 0,
}
local function map(dest, source)
for k,v in pairs(source) do
dest[k] = v
end
return dest
end
local function calc_used_mem_size(env)
local size = 0
for key,val in pairs(env) do
if type(val) == "table" and val.size ~= nil then
size = size + val.size() or 0
end
end
return size
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 format_error_str(str, label)
local tbl = {}
for s in str:gmatch("[^\r\n]+") do
s = s:match("^%s*(.-)%s*$")
if s:find("function 'xpcall'") then
break
elseif s:find(".-%.lua:%d+:(.+)") then
local err = s:gsub(".-%.lua:%d+:%s*(.+)", "extern: %1")
table.insert(tbl, err)
elseif s:find('%[string ".-"%]') then
local line, err = s:match('^%[string ".-"%]:(%d+): (.+)$')
table.insert(tbl, label..":"..line..": "..err)
elseif s:find('%(load%):(%d+):') then
local line, err = s:match('%(load%):(%d+): (.+)$')
table.insert(tbl, label..":"..line..": "..err)
end
end
return "Error: "..table.concat(tbl, "\n >> ")
end
local function format_error(err, label)
if err:find("stack overflow") then
return "Error: Stack overflow due to recursive function calls!"
end
return format_error_str(err, label)
end
local function compile(pos, text, label, err_clbk)
if safer_lua:check(pos, text, label, err_clbk) == 0 then
text = text:gsub("%$", "S:")
local code, err = loadstring(text)
if not code then
err_clbk(pos, format_error(err, label))
else
return code
end
end
end
-------------------------------------------------------------------------------
-- Standard init/loop controller
-------------------------------------------------------------------------------
function safer_lua.init(pos, init, loop, environ, err_clbk)
if (#init + #loop) > safer_lua.MaxCodeSize then
err_clbk(pos, "Error: Code size limit exceeded")
return
end
local code = compile(pos, init, "init", err_clbk, 0)
if code then
local env = table.copy(BASE_ENV)
env.S = {}
env.S = map(env.S, environ)
setfenv(code, env)
local res, err = xpcall(code, debug.traceback)
if not res then
err_clbk(pos, format_error(err, "init"))
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.elapsed = elapsed
if elapsed < 0 then -- event?
env.event = true
else
env.event = false
env.ticks = env.ticks + 1
end
local res, err = xpcall(code, debug.traceback)
if calc_used_mem_size(env) > safer_lua.MaxTableSize then
err_clbk(pos, "Error: Data memory limit exceeded")
return false
end
if not res then
err_clbk(pos, format_error(err, "loop"))
return false
end
return true
end
-------------------------------------------------------------------------------
-- Endless/Coroutine controller
-------------------------------------------------------------------------------
local function thread(pos, code, err_clbk)
while true do
local res, err = xpcall(code, debug.traceback)
if not res then
err_clbk(pos, format_error(err, "loop"))
return false
end
local env = getfenv(code)
if calc_used_mem_size(env) > safer_lua.MaxTableSize then
err_clbk(pos, "Error: Memory limit exceeded")
return false
end
coroutine.yield()
end
end
function safer_lua.co_create(pos, init, loop, environ, err_clbk)
local code = safer_lua.init(pos, init, loop, environ, err_clbk)
return coroutine.create(thread), code
end
function safer_lua.co_resume(pos, co, code, err_clbk)
local res, err = coroutine.resume(co, pos, code, err_clbk)
if not res then
err_clbk(pos, format_error(err, "loop"))
return false
end
return true
end

19
init.lua Normal file
View File

@ -0,0 +1,19 @@
--[[
SaferLua [safer_lua]
====================
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
environ.lua:
]]--
safer_lua = {}
dofile(minetest.get_modpath("safer_lua") .. "/data_struct.lua")
dofile(minetest.get_modpath("safer_lua") .. "/scanner.lua")
dofile(minetest.get_modpath("safer_lua") .. "/environ.lua")

1
mod.conf Normal file
View File

@ -0,0 +1 @@
name=safer_lua

19
readme.md Normal file
View File

@ -0,0 +1,19 @@
SaferLua [safer_lua] v0.01
==========================
A subset of the language Lua for safe and secure Lua sandboxes with:
- limited code length
- limited execution time
- limited memory use
- limited posibilities to call functions
### License
Copyright (C) 2018 Joachim Stolberg
Code: Licensed under the GNU LGPL version 2.1 or later. See LICENSE.txt
### Dependencies
none
### History
- 2018-06-24 v0.01 * first draft

141
scanner.lua Normal file
View File

@ -0,0 +1,141 @@
--[[
SaferLua [safer_lua]
====================
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
scanner.lua:
]]--
local function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function safer_lua:word(ch, pttrn)
local word = ""
while ch:match(pttrn) do
word = word .. ch
self.pos = self.pos + 1
ch = self.line:sub(self.pos, self.pos)
end
return word
end
function safer_lua:string(pttrn)
self.pos = self.pos + 1
local ch = self.line:sub(self.pos, self.pos)
while not ch:match(pttrn) and self.pos < #self.line do
if ch == "\\" then
self.pos = self.pos + 1
end
self.pos = self.pos + 1
ch = self.line:sub(self.pos, self.pos)
end
self.pos = self.pos + 1
-- result is not needed
end
local function lines(str)
local t = {}
local function helper(line)
table.insert(t, line)
return ""
end
helper((str:gsub("(.-)\r?\n", helper)))
return t
end
function safer_lua:scanner(text)
local lToken = {}
for idx, line in ipairs(lines(text)) do
self.line = line
self.pos = 1
self.line = trim(self.line)
self.line = self.line:split("--", true)[1]
table.insert(lToken, idx) -- line number
if self.line then
-- devide line in tokens
while true do
if self.pos > #self.line then break end
local ch = self.line:sub(self.pos, self.pos)
if ch:match("[%u%l_]") then -- identifier?
table.insert(lToken, self:word(ch, "[%w_]"))
elseif ch:match("[%d]") then -- number?
table.insert(lToken, self:word(ch, "[%d%xx]"))
elseif ch:match("'") then -- string?
self:string("'")
elseif ch:match('"') then -- string?
self:string('"')
elseif ch:match("[%s]") then -- Space?
self.pos = self.pos + 1
elseif ch:match("[:{}]") then -- critical tokens?
table.insert(lToken,ch)
self.pos = self.pos + 1
else
self.pos = self.pos + 1
end
end
end
end
return lToken
end
local InvalidKeywords = {
["while"] = true,
["repeat"] = true,
["until"] = true,
["for"] = true,
["range"] = true,
--["function"] = true,
["_G"] = true,
["__load"] = true,
["__dump"] = true,
}
local InvalidChars = {
[":"] = true,
["{"] = true,
["["] = true,
["]"] = true,
["}"] = true,
}
function safer_lua:check(pos, text, label, err_clbk)
local lToken = self:scanner(text)
local lineno = 0
local errno = 0
for idx,token in ipairs(lToken) do
if type(token) == "number" then
lineno = token
elseif InvalidKeywords[token] then
if token == "for" then
-- invalid for statement?
if lToken[idx + 3] == "in" and lToken[idx + 5] == "next" then
--
elseif lToken[idx + 2] == "in" and lToken[idx + 3] == "range" then
--
else
err_clbk(pos, label..":"..lineno..": Invalid use of 'for'")
errno = errno + 1
end
elseif token == "range" then
if lToken[idx - 1] ~= "in" then
err_clbk(pos, label..":"..lineno..": Invalid use of 'range'")
errno = errno + 1
end
else
err_clbk(pos, label..":"..lineno..": Invalid keyword '"..token.."'")
errno = errno + 1
end
elseif InvalidChars[token] then
err_clbk(pos, label..":"..lineno..": Invalid character '"..token.."'")
errno = errno + 1
end
end
return errno
end

203
test_data_struct.lua Normal file
View File

@ -0,0 +1,203 @@
core = {}
function core.global_exists(name)
return false
end
dofile('/home/joachim/minetest4/builtin/common/vector.lua')
dofile('/home/joachim/minetest4/builtin/common/misc_helpers.lua')
safer_lua = {}
safer_lua.MaxTableSize = 1000 -- number of table entries considering string lenghts
dofile('/home/joachim/minetest4/mods/techpack/safer_lua/data_struct.lua')
print("Array")
local a = safer_lua.Array(1,2,3,4) --> {1,2,3,4}
a.add(6) --> {1,2,3,4,6}
a.set(2, 8) --> {1,8,3,4,6}
a.insert(5,7) --> {1,8,3,4,7,6}
print(dump(a.__dump()))
a.remove(3) --> {1,8,4,7,6}
a.insert(1, "hello") --> {"hello",1,8,4,7,6}
print(a.size()) --> function returns 10
print(dump(a.__dump()))
print("Store")
local s = safer_lua.Store() --> {}
s.set("val", 12) --> {val = 12}
s.get("val") --> returns 12
s.set(0, "hello") --> {val = 12, [0] = "hello"}
print(dump(s.__dump()))
s.del("val") --> {[0] = "hello"}
print(s.size()) --> function returns 6
print("Set")
s = safer_lua.Set("Tom", "Lucy", "Joe") --> {Tom = true, Lucy = true, Joe = true}
s.add("Susi") --> {Tom = true, Lucy = true, Joe = true, Susi = true}
s.del("Tom") --> {Lucy = true, Joe = true, Susi = true}
print(dump(s.__dump()))
print(s.has("Joe")) --> function returns `true`
print(s.has("Mike")) --> function returns `false`
print(s.size()) --> function returns 11
print("S1")
local s1 = safer_lua.Store()
assert(s1.size() == 0)
s1.a = 3
s1[1] = 4
assert(s1.size() == 0)
s1.set("b", "Hallo")
assert(s1.size() == 1)
assert(s1.memsize() == 6)
s1.set("b", "Hall")
assert(s1.size() == 1)
assert(s1.memsize() == 5)
assert(s1.get("b") == "Hall")
assert(s1.size() == 1)
s1.set("1234", "12345678")
assert(s1.size() == 2)
assert(s1.memsize() == 17)
s1.del("1234")
print(s1.size())
assert(s1.size() == 1)
assert(s1.memsize() == 5)
assert(s1.get("1234") == nil)
print("S2")
local s2 = safer_lua.Store()
assert(s2.size() == 0)
assert(s2.memsize() == 0)
s2.set("b", "Joe")
assert(s2.size() == 1)
assert(s2.memsize() == 4)
assert(s2.b == nil)
assert(s2.get('b') == "Joe")
s2.c = "XXX!"
assert(s2.c == nil)
s1.set("c", s2)
print(dump(s1.get("c")))
assert(s1.size() == 2)
print(s1.memsize())
assert(s1.memsize() == 10)
assert(s2.size() == 1)
assert(s2.memsize() == 4)
print("A1")
local a1 = safer_lua.Array(1,2,3,4)
assert(a1.size() == 4)
print(dump(a1))
a1.set(2, "Hallo")
assert(a1.size() == 4)
assert(a1.memsize() == 8)
a1.insert(1, 0)
assert(a1.size() == 5)
assert(a1.memsize() == 9)
a1.remove(3)
assert(a1.size() == 4)
assert(a1.memsize() == 4)
print(a1.MemSize)
print(a1.Size)
print("Set")
local s3 = safer_lua.Set("Joe", "Bob", "Tom")
print(s3.size())
s3.add("Susi")
local t = s3.__dump()
print(dump(t))
s3.del("Tom")
assert(s3.has("Susi") == true)
assert(s3.has("Mike") == false)
print(s3.size())
assert(s3.size() == 3)
assert(s3.memsize() == 10)
local s4 = safer_lua.Set()
s4.__load(3, 12, {Joe=true, Bob=true, Tom=true})
assert(s4.has("Joe") == true)
assert(s4.has("Mike") == false)
print(s4.size())
assert(s4.size() == 3)
assert(s4.memsize() == 12)
local tbl = safer_lua.datastruct_to_table(s3)
s3 = safer_lua.table_to_datastruct(tbl)
assert(s3.has("Susi") == true)
assert(s3.has("Mike") == false)
print(s3.size())
assert(s3.size() == 3)
assert(s3.memsize() == 10)
tbl = safer_lua.datastruct_to_table(a1)
a1 = safer_lua.table_to_datastruct(tbl)
assert(a1.size() == 4)
assert(a1.memsize() == 4)
assert(a1.get(4) == 4)
tbl = safer_lua.datastruct_to_table(s2)
s2 = safer_lua.table_to_datastruct(tbl)
assert(s2.size() == 1)
assert(s2.memsize() == 4)
assert(s2.get("b") == "Joe")
print("next over Array")
local a2 = safer_lua.Array(10, 20, 30)
for i,v in a2.next() do
print(i,v)
end
print("next over Set")
local s6 = safer_lua.Set("Joe", "Bob", "Tom")
for i,v in s6.next() do
print(i,v)
end
print("next over Store")
local s7 = safer_lua.Store() --> {}
s7.set("a", 12)
s7.set("b", 13)
s7.set("c", 14)
for k,v in s7.next() do
print(k,v)
end
print("sort")
a3 = safer_lua.Array("Joe", "Bob", "Tom")
a3.sort(true)
print(dump(a3.__dump()))
a3.sort()
print(dump(a3.__dump()))
s7 = safer_lua.Store()
s7.set("Joe", 1000)
s7.set("Susi", 800)
s7.set("Tom", 60)
s7.set("Mike", 900)
s7.set("Bob", 1100)
local k = s7.keys()
print(dump(k.__dump()))
local k = s7.keys("up")
print(dump(k.__dump()))
local k = s7.keys("down")
print(dump(k.__dump()))

94
test_environ.lua Normal file
View File

@ -0,0 +1,94 @@
core = {}
function core.global_exists(name)
return false
end
dofile('/home/joachim/minetest4/builtin/common/vector.lua')
dofile('/home/joachim/minetest4/builtin/common/misc_helpers.lua')
safer_lua = {}
dofile('/home/joachim/minetest4/mods/techpack/safer_lua/data_struct.lua')
dofile('/home/joachim/minetest4/mods/techpack/safer_lua/scanner.lua')
dofile('/home/joachim/minetest4/mods/techpack/safer_lua/environ.lua')
--local Cache = {}
--local key = minetest.pos_to_hash(pos)
--code = Cache[key]
local function foo(self, val)
print("Hallo", val)
end
local function error(pos, s)
print("[Test] "..(s or "").." at pos "..dump(pos))
end
local init = "fo"
local loop = [[
--$loopcycle(5)
--$events(true)
$foo("hallo")
$foo("hallo")
$foo(math.floor(5.5))
$foo("Joe")
a = Store()
a.set("a", 123)
a.set("b", 456)
$foo(a.get("a"))
$foo(ticks)
if ticks == 10 then $foo("Fehler") end
for k,v in a.next() do
$foo(k)
end
--for k = 1,4,1 do
-- next = 3
-- $foo(k)
--end
--$foo(meta.pos)
]]
local init2 = [[
meme = "\n\n\"" while true do end meme = ""
]]
local env = {foo = foo}
env.meta = {pos=1, owner="Joe", number="0123"}
local code = safer_lua.init(0, init, "", loop, env, error)
if code then
print(safer_lua.run_loop(0, 0, code, error))
safer_lua.run_loop(0, 1, code, error)
safer_lua.run_loop(0, 2, code, error)
end
print("\n<<< Coroutine >>>\n")
local function outp(self, val)
print(val)
end
local function step(self, num)
for i=1,num do
print(i)
coroutine.yield()
end
end
local thread = [[
$outp("hallo")
$step(2)
$outp(meta.pos)
]]
env = {step = step, outp = outp}
env.meta = {pos=1, owner="Joe", number="0123", error=error}
local co, code = safer_lua.co_create(0, init, thread, env, error)
if code then
for i=1,20 do
if safer_lua.co_resume(0, co, code, error) == false then break end
end
end

41
test_scanner.lua Normal file
View File

@ -0,0 +1,41 @@
core = {}
function core.global_exists(name)
return false
end
safer_lua = {}
dofile('/home/joachim/minetest4/builtin/common/vector.lua')
dofile('/home/joachim/minetest4/builtin/common/misc_helpers.lua')
dofile('/home/joachim/minetest4/mods/techpack/safer_lua/scanner.lua')
code = [[
-- GOOD
a = 1
a = a + 1
print(a)
foo(a)
-- BAD
_G.print(()
t = {}
for i = 1,1000 do
]]
code2 = [[
meme = "\"" while true do end meme = ""
]]
code3 = "s = [[abc]]"
local function error(pos, s)
print("[Robbi] "..s)
end
safer_lua:check(nil, code, "Code", error)
lToken = safer_lua:scanner(code2)
safer_lua:check(nil, code2, "Code", error)
lToken = safer_lua:scanner(code3)
safer_lua:check(nil, code3, "Code", error)

59
test_store.lua Normal file
View File

@ -0,0 +1,59 @@
core = {}
function core.global_exists(name)
return false
end
dofile('/home/joachim/minetest/builtin/common/vector.lua')
dofile('/home/joachim/minetest/builtin/common/misc_helpers.lua')
safer_lua = {}
safer_lua.MaxTableSize = 1000 -- number of table entries considering string lenghts
dofile('/home/joachim/minetest4/mods/techpack/safer_lua/data_struct.lua')
local s1 = safer_lua.Store()
local s2 = safer_lua.Store()
print("S1")
assert(s1.size() == 0)
s1.a = 3
assert(s1.size() == 0)
s1.set("b", "Hallo")
assert(s1.size() == 1)
assert(s1.get("b") == "Hallo")
assert(s1.size() == 1)
print("S2")
assert(s2.size() == 0)
s2.set("b", "Joe")
assert(s2.size() == 1)
assert(s2.b == nil)
s2.c = "XXX!"
assert(s2.c == nil)
s1.set("c", s2)
print(s1.get("c"))
local s3 = safer_lua.Store("a", 4, "b", 5, "c")
assert(s3.get("a") == 4)
assert(s3.get("b") == 5)
assert(s3.get("c") == nil)
s = safer_lua.Store("a", 4, "b", 5) --> {a = 4, b = 5}
--s = safer_lua.Store() --> {a = 4, b = 5}
s.set("val", 12) --> {a = 4, b = 5, val = 12}
s.get("val") --> returns 12
s.set(0, "hello") --> {a = 4, b = 5, val = 12, [0] = "hello"}
s.del("val") --> {a = 4, b = 5, [0] = "hello"}
print(s.size()) --> function returns 3
print(s.memsize()) --> function returns 8
print("Ready.")