Switched to a method proposed by @SoniEx2 to disallow function calls (#15).

This commit is contained in:
Paul Kulchenko 2015-01-24 13:53:57 -08:00
parent 9ed094ba07
commit d78f212b71
2 changed files with 16 additions and 38 deletions

View File

@ -104,42 +104,16 @@ local function s(t, opts)
end end
local function deserialize(data, opts) local function deserialize(data, opts)
local f, res = (loadstring or load)('return '..data) local env = (opts and opts.safe == false) and G
if not f then f, res = (loadstring or load)(data) end or setmetatable({}, {
__index = function(t,k) return t end,
__call = function(t,...) error("cannot call functions") end
})
local f, res = (loadstring or load)('return '..data, nil, nil, env)
if not f then f, res = (loadstring or load)(data, nil, nil, env) end
if not f then return f, res end if not f then return f, res end
if opts and opts.safe == false then return pcall(f) end if setfenv then setfenv(f, env) end
return pcall(f)
local setfenv, getfenv = setfenv, getfenv
if not setfenv then -- Lua 5.2+
-- based on http://lua-users.org/lists/lua-l/2010-06/msg00314.html
-- this assumes f is a function
local function findenv(f)
local level = 1
repeat
local name, value = debug.getupvalue(f, level)
if name == '_ENV' then return level, value end
level = level + 1
until name == nil
return nil end
getfenv = function (f) return(select(2, findenv(f)) or _G) end
setfenv = function (f, t)
local level = findenv(f)
if level then debug.setupvalue(f, level, t) end
return f end
end
local env = {}
env._G = setmetatable(env, { __index = getfenv(f) })
f = setfenv(f, env)
local count, thread = 0, coroutine.running()
local h, m, c = debug.gethook(thread)
debug.sethook(function (e, l) count = count + 1
if count >= 3 then error("cannot call functions") end
end, "c")
local res = {pcall(f)}
count = 0 -- set again, otherwise it's tripped on the next sethook
debug.sethook(thread, h, m, c)
return (table.unpack or unpack)(res)
end end
local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end

View File

@ -400,15 +400,19 @@ do
local print = _G.print local print = _G.print
local ok, res = serpent.load("do print = error end") local ok, res = serpent.load("do print = error end")
assert(ok and _G.print == print and print ~= error, assert(ok and _G.print == print and print ~= error,
"not allowing resetting `print` from serialized content (1/3): failed") "not allowing resetting `print` from serialized content (1/4): failed")
local ok, res = serpent.load("do _G.print = error end") local ok, res = serpent.load("do _G.print = error end")
assert(ok and _G.print == print and _G.print ~= error, assert(ok and _G.print == print and _G.print ~= error,
"not allowing resetting `print` from serialized content (2/3): failed") "not allowing resetting `print` from serialized content (2/4): failed")
local ok, res = serpent.load("do _G._G.print = error end") local ok, res = serpent.load("do _G._G.print = error end")
assert(ok and _G.print == print and print ~= error, assert(ok and _G.print == print and print ~= error,
"not allowing resetting `print` from serialized content (3/3): failed") "not allowing resetting `print` from serialized content (3/4): failed")
local ok, res = serpent.load("do _G = nil _G.print = error end")
assert(ok and _G.print == print and print ~= error,
"not allowing resetting `print` from serialized content (4/4): failed")
end end
print("All tests passed.") print("All tests passed.")