在 Lua 5.2 中重新创建 setfenv() [英] Recreating setfenv() in Lua 5.2

查看:58
本文介绍了在 Lua 5.2 中重新创建 setfenv()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在 Lua 5.2 中重新创建 setfenv 的功能?我在理解您应该如何使用新的 _ENV 环境变量时遇到了一些麻烦.

How can I recreate the functionality of setfenv in Lua 5.2? I'm having some trouble understanding exactly how you are supposed to use the new _ENV environment variable.

在 Lua 5.1 中,您可以使用 setfenv 轻松沙盒任何函数.

In Lua 5.1 you can use setfenv to sandbox any function quite easily.

--# Lua 5.1

print('_G', _G)             -- address of _G

local foo = function()  
    print('env', _G)        -- address of sandbox _G
    bar = 1
end

-- create a simple sandbox
local env = { print = print }
env._G = env

-- set the environment and call the function
setfenv(foo, env)
foo()

-- we should have global in our environment table but not in _G
print(bar, env.bar)

运行此示例显示输出:

_G    table: 0x62d6b0
env   table: 0x635d00
nil   1



我想在 Lua 5.2 中重新创建这个简单的例子.下面是我的尝试,但它不像上面的例子那样工作.



I would like to recreate this simple example in Lua 5.2. Below is my attempt, but it does not work like the above example.

--# Lua 5.2

local function setfenv(f, env)
    local _ENV = env or {}       -- create the _ENV upvalue
    return function(...)
        print('upvalue', _ENV)   -- address of _ENV upvalue
        return f(...)
    end
end

local foo = function()
    print('_ENV', _ENV)          -- address of function _ENV
    bar = 1
end

-- create a simple sandbox
local env = { print = print }
env._G = env

-- set the environment and call the function
foo_env = setfenv(foo, env)
foo_env()

-- we should have global in our envoirnment table but not in _G
print(bar, env.bar)

运行此示例显示输出:

upvalue    table: 0x637e90
_ENV       table: 0x6305f0
1          nil



我知道关于这个主题的其他几个问题,但它们似乎主要是处理加载动态代码(文件或字符串),使用 Lua 5.2 中提供的新 load 函数可以很好地工作.在这里,我特别要求一种在沙箱中运行任意函数的解决方案.我想在不使用 debug 库的情况下做到这一点.根据 Lua 文档,我们不应该依赖它.



I am aware of several other questions on this subject, but they mostly seem to be dealing with loading dynamic code (files or string) which work quite well using the new load function provided in Lua 5.2. Here I am specifically asking for a solution to run arbitrary functions in a sandbox. I would like to do this without using the debug library. According to the Lua documentation we should not have to rely on it.

推荐答案

如果不使用 Lua 5.2 中的 Lua 调试库,您将无法更改函数的环境.一旦创建了一个函数,这就是它所拥有的环境.修改这个环境的唯一方法是修改它的第一个upvalue,这需要调试库.

You cannot change the environment of a function without using the debug library from Lua in Lua 5.2. Once a function has been created, that is the environment it has. The only way to modify this environment is by modifying its first upvalue, which requires the debug library.

Lua 5.2 中环境的一般想法是,环境应该被认为是不可变的,而不是欺骗(即:调试库).你在一个环境中创建一个函数;一旦在那里创建,那就是它的环境.永远.

The general idea with environments in Lua 5.2 is that the environment should be considered immutable outside of trickery (ie: the debug library). You create a function in an environment; once created there, that's the environment it has. Forever.

这就是 Lua 5.1 中经常使用的环境的方式,但是通过随意的函数调用来修改任何环境的环境是很容易和被认可的.如果你的 Lua 解释器去掉了 setfenv(防止用户破坏沙箱),那么用户代码就不能在内部为自己的函数设置环境.所以外部世界有一个沙箱,但内部世界不能有沙箱在沙箱内.

This is how environments were often used in Lua 5.1, but it was easy and sanctioned to modify the environment of anything with a casual function call. And if your Lua interpreter removed setfenv (to prevent users from breaking the sandbox), then the user code can't set the environment for their own functions internally. So the outside world gets a sandbox, but the inside world can't have a sandbox within the sandbox.

Lua 5.2 机制使得在创建函数后更难修改环境,但它确实允许您在创建过程中设置环境.这让您可以在沙箱中进行沙箱.

The Lua 5.2 mechanism makes it harder to modify the environment post function-creation, but it does allow you to set the environment during creation. Which lets you sandbox inside the sandbox.

所以你真正想要的是像这样重新排列你的代码:

So what you really want is to just rearrange your code like this:

local foo;

do
  local _ENV = { print = print }

  function foo()
    print('env', _ENV)
    bar = 1
  end
end

foo 现在被沙盒化了.而现在,要打破沙盒的难度要大得多.

foo is now sandboxed. And now, it's much harder for someone to break the sandbox.

你可以想象,这在 Lua 开发者中引起了一些争论.

As you can imagine, this has caused some contention among Lua developers.

这篇关于在 Lua 5.2 中重新创建 setfenv()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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