Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lua沙箱具有特殊的泄漏功能_Lua_Sandbox - Fatal编程技术网

Lua沙箱具有特殊的泄漏功能

Lua沙箱具有特殊的泄漏功能,lua,sandbox,Lua,Sandbox,我正试图用它来建造我自己的漏水沙箱 我试图创建一个Lua沙盒,其中一些Lua函数可以访问沙盒之外的其他Lua函数。例如,我希望我的沙盒有一个特殊的“显示”功能,可以调用“打印”,但沙盒中没有“打印” 主要的问题是,我试图在一个已经很大的代码库中构建一个沙盒,因此我无法消除函数 这怎么可能 由于没有我的错误,解决方案必须是纯Lua函数。它是否特别需要调用Lua标准库print函数?您是否可以模拟打印的功能?因为那是最简单的方法 但是,如果您想在print周围有一个包装器,有两种方法可以做到这一点:

我正试图用它来建造我自己的漏水沙箱

我试图创建一个Lua沙盒,其中一些Lua函数可以访问沙盒之外的其他Lua函数。例如,我希望我的沙盒有一个特殊的“显示”功能,可以调用“打印”,但沙盒中没有“打印”

主要的问题是,我试图在一个已经很大的代码库中构建一个沙盒,因此我无法消除函数

这怎么可能


由于没有我的错误,解决方案必须是纯Lua函数。

它是否特别需要调用Lua标准库
print
函数?您是否可以模拟打印的功能?因为那是最简单的方法

但是,如果您想在
print
周围有一个包装器,有两种方法可以做到这一点:使用纯Lua代码和使用C/C++代码

纯Lua溶液如下所示。请注意,这应该在加载任何外部脚本之前完成。首先,打开包含
print
的Lua标准库。然后运行此Lua脚本:

local internal_print = print

return function(...)
    --Do display logic.
    internal_print(...) --Or whatever else you want.
end
这将返回“显示”功能。如果愿意,可以将其存储在名为
display
的全局变量中,也可以调用其他变量

之后,您可以
nil
输出
print
全局变量,从而使其几乎完全不可访问

如果您想从C/C++中实现它,它非常类似。首先,与前面一样,注册包含
print
的Lua标准库,以便获得该库的函数。然后,使用
lua\u getglobal(L,“print”)
获取
print
函数并将其推到堆栈上。接下来,使用
lua\u pushcclosure
注册C/C++函数。但是您希望指定一个upvalue,Lua在注册时从堆栈中弹出该值

现在,您注册的函数位于堆栈上,等待被推送到Lua变量或全局表条目中


警告:Lua调试库可以戳取upvalues,从而从新函数中获取
print
函数。因此,如果您希望获得完美的安全性,那么在创建沙盒时,可以通过从更大的环境中选取函数和值来创建新的沙盒环境,从而摆脱
debug.getupvalue

。您不需要在原始环境中销毁或“取消”任何内容

  • 通过选择函数和值来创建沙箱环境
  • 加载脚本(编译脚本并将其作为要调用的函数返回)
  • 将脚本的环境设置为沙盒环境
  • 在沙箱中执行脚本
  • 所以

    印刷品

    0.69314718055995
    
    鉴于

    local script = loadstring "print(math.log(2, 3))"
    local env = {display = print, math = math, string = string}
    setfenv(script, env)
    pcall(script)
    
    失败于

    false   [string "print(math.log(2, 3))"]:1: attempt to call global 'print' (a nil value)
    
    构建您的沙盒(或者多个沙盒,如果每个沙盒有不同的需求),并将不受信任的代码一次一个地移动到沙盒中。在我的quick cli测试中,5.1和5.2都将运行在沙箱外部定义的函数,而无需修改。要使用Doug的示例,假设
    display
    是使用
    print
    的现有代码的一部分:

    --5.1
    本地功能显示(…)
    打印(…)
    结束
    本地脚本=loadstring“显示(math.log(2,3))”
    本地环境={display=display,math=math,string=string}
    塞特芬夫(脚本,环境)
    打印(pcall(脚本))
    -- 5.2
    本地功能显示(…)
    打印(…)
    结束
    本地脚本=loadstring“显示(math.log(2,3))”
    本地环境=_环境
    _ENV={display=display,math=math,string=string}
    e、 打印(e.pcall(脚本))
    _环境=e
    
    请注意,在上述两个示例中,
    display
    函数正在使用
    print
    ,而不修改该代码,因为创建该函数时您不在沙箱中

    在过去,我存储了一个指向非沙盒环境的本地指针,但我无法重现quick cli测试中需要的情况。如果你能给出一个例子,我可能会想出一个不需要
    e
    变量的解决方法。下面是使用5.2的代码示例:

    local e=_ENV
    
    for k,v in e.pairs(value) do
    -- iterate
    end
    
    另一个例子,对于我的只读表代码,我再次使用
    e

    function ro_table (t)
      local t = t
      if t then
        return e.setmetatable({}, 
          { __index=t, 
            __newindex= function(_,_,_) e.error ("Attempt to modify read-only table") end, 
          })
      else
        return nil
      end
    end
    

    “印刷品”只是一个简单的例子来解释这个概念。此外,我不能取消旧的“打印”,因为有大量的代码可以直接访问它。这似乎接近我想要的。我会试试看它是否能按我需要的方式工作。
    function ro_table (t)
      local t = t
      if t then
        return e.setmetatable({}, 
          { __index=t, 
            __newindex= function(_,_,_) e.error ("Attempt to modify read-only table") end, 
          })
      else
        return nil
      end
    end