不污染全局环境的Loadfile [英] Loadfile without polluting global environment

查看:20
本文介绍了不污染全局环境的Loadfile的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在不污染全局环境的情况下加载lua表和变量的文件?由于执行加载文件并运行它只会加载全局空间中的所有内容,并且可能会覆盖我不想要的其他内容.

How can I load a file of lua tables and variables without polluting the global environment? Since doing a loadfile and running it just loads everything in the global space and may overwrite something else which I don't want.

推荐答案

在 Lua 5.1 中,无需太多错误处理,您可以这样做:

In Lua 5.1 and without much error handling you could do this:

-- load and run a script in the provided environment
-- returns the modified environment table
function run(scriptfile)
    local env = setmetatable({}, {__index=_G})
    assert(pcall(setfenv(assert(loadfile(scriptfile)), env)))
    setmetatable(env, nil)
    return env
end

第一行创建了一个空的环境表,可以看到所有现有的全局变量,但不能简单地改变它们,因为它们只能通过 __index 元方法通过代理可见.脚本创建的任何全局变量都将存储在返回的 env 中.这适用于只设置一堆配置参数的简单脚本,并且可能需要调用简单的安全函数来根据运行时的条件设置它们.

The first line creates an empty environment table that can see all existing globals, but which cannot trivially change them since they are visible only by proxy through the __index metamethod. Any globals the script creates would be stored in env, which is returned. This will work well for simple scripts that just set a bunch of configuration parameters, and which might need to call simple safe functions to set them based on conditions at run time.

请注意,让脚本对全局变量可见是很方便的.尽管不能以明显的方式从脚本中修改全局变量,但 _G 是一个全局变量,包含对全局环境的引用(包含 _G._G, _G._G._G 等...) 和 _G 可以从脚本中修改,这可能会导致进一步的问题.

Note that making the globals visible to the script is a convenience. Although the globals cannot be modified from the script in the obvious way, _G is a global variable that contains a reference to the global environment (containing _G._G, _G._G._G, etc...) and _G can be modified from the script which could lead to further issues.

因此,与其使用 _G 作为索引,不如构造一个仅包含已知安全且已知脚本作者需要的函数的表.

So rather than using _G for the index, it would be much better to construct a table that contains only functions known to be safe and known to be needed by your script's author.

一个完整的解决方案是在沙箱中运行脚本,并可能进一步保护以防止意外(或故意)拒绝服务或更糟.沙箱在 Lua 用户的 Wiki 中有更详细的介绍.这个话题比乍一看更深入,但只要您的用户被信任是非恶意的,那么实用的解决方案就很简单.

A complete solution would be to run the script in a sandbox, and possibly further protected to prevent accidental (or deliberate) denial of service or worse. Sandboxes are covered in more detail at the Lua User's Wiki. The topic is deeper than it seems at first glance, but as long as your users are trusted to be non-malicious then practical solutions are straightforward.

Lua 5.2 通过消除 setfenv() 来支持 load() 的新参数,从而稍微改变了一些事情.详细信息也在 wiki 页面中.

Lua 5.2 changes things a little bit by eliminating setfenv() in favor of a new parameter to load(). Details are also in the wiki page.

这篇关于不污染全局环境的Loadfile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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