Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.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
C++ 如何从C API在自己的环境中执行不受信任的Lua文件_C++_C_Lua_Lua Api - Fatal编程技术网

C++ 如何从C API在自己的环境中执行不受信任的Lua文件

C++ 如何从C API在自己的环境中执行不受信任的Lua文件,c++,c,lua,lua-api,C++,C,Lua,Lua Api,我想通过调用在自己的环境中执行一个不受信任的.lua文件,这样它就不会影响我的任何代码 不过,该函数的文档只解释了如何调用函数,而不是如何执行文件 当前要运行我使用的文件,请执行以下操作: int error = luaL_loadfile(mState, path.c_str()) || lua_pcall(mState, 0, 0, 0); 我必须用lua\u setfenv从C API调用“dofile”lua函数吗?还是有更优雅的方法呢?lua\u loadfile()将加载块,然后调

我想通过调用在自己的环境中执行一个不受信任的.lua文件,这样它就不会影响我的任何代码

不过,该函数的文档只解释了如何调用函数,而不是如何执行文件

当前要运行我使用的文件,请执行以下操作:

int error = luaL_loadfile(mState, path.c_str()) || lua_pcall(mState, 0, 0, 0);

我必须用
lua\u setfenv
从C API调用“dofile”lua函数吗?还是有更优雅的方法呢?

lua\u loadfile()
将加载块,然后调用
lua\u setfenv()
设置环境表,然后调用
lua\u pcall()
执行块。参见Judge Maygarden在

上给出的最新答案参见的Lua用户维基上的讨论,以及的更一般主题。这类事情有很多微妙和不那么微妙的问题。这是可以做到的,但是防止i=1,1e39 do end等代码需要的不仅仅是限制沙箱可用的函数

一般技术是为沙盒创建一个函数环境,其中包含一个允许函数的白名单。在某些情况下,该列表甚至可能为空,但例如,让用户访问
pairs()
,几乎肯定是无害的。沙盒页面有一个按安全性划分的系统功能列表,作为构建此类白名单的方便参考

然后使用
lua\u setfenv()
将函数环境应用于用户的脚本,该脚本已使用
lua\u loadfile()
lua\u loadstring()
加载(但尚未执行)。连接环境后,您可以使用
lua\u pcall()
和朋友执行它。在执行之前,有些人实际上已经扫描了加载的字节码,查找他们不想允许的操作。可用于绝对禁止循环或写入全局变量

另一个注意事项是加载函数通常会加载预编译字节码或Lua文本。事实证明,如果您不允许预编译字节码,那么它会安全得多,因为已经发现了许多使VM行为异常的方法,它们都依赖于手工制作无效字节码。由于字节码文件以非纯ASCII文本的定义良好的字节序列开头,因此您只需将脚本读入字符串缓冲区,测试是否缺少标记,如果不是字节码,则只将其传递给
lua\u loadstring()


在过去的几年里,关于这类事情的讨论相当多,因此在那里搜索可能也会有所帮助。

顺便说一句,这就是我最终要做的:

/* Loads, compiles and executes an unstrusted file. */
bool Lua::RunUntrustedFile(const string& path)
{
    if(luaL_loadfile(mState, path.c_str()))
    {
        ErrorLog(lua_tostring(mState, 1));
        Pop(1);
        return false;
    }

    Lua::SetMaximumInstructions(100000000);
    lua_newtable(mState);
    lua_setglobal(mState, "upload");
    ASSERT(Lua::GetStackSize() == 1);
    lua_getglobal(mState, "upload");
    ASSERT_ALWAYS(lua_setfenv(mState, 1) != 0);
    ASSERT(Lua::GetStackSize() == 1);

    if(lua_pcall(mState, 0, 0, 0))
    {
        Lua::ClearMaximumInstructions();
        ErrorLog(lua_tostring(mState, -1));
        Pop(1);
        return false;
    }

    ASSERT(Lua::GetStackSize() == 0);
    Lua::ClearMaximumInstructions();

    return true;
}
“支持”功能:

static void Pop(int elements = 1) { lua_pop(mState, elements); }

/* Sets a maximum number of instructions before throwing an error */
static void SetMaximumInstructions(int count) {
    lua_sethook(mState, &Lua::MaximumInstructionsReached, LUA_MASKCOUNT, count);
}
static void ClearMaximumInstructions() {
    lua_sethook(mState, &Lua::MaximumInstructionsReached, 0, 0);
}

static void MaximumInstructionsReached(lua_State *, lua_Debug *)
{
    Error("The maximum number of instructions has been reached");
}

static int GetStackSize() { return lua_gettop(mState); }

非常感谢。我已经通过设置一个调试钩子来处理无限循环,该钩子在1000万条指令之后终止脚本。至于函数,用户提供的文件只包含全局变量,没有任何函数,因此我不必将任何函数列为白名单。