如何在不编辑Lua头文件或脚本的情况下从os库中删除特定函数

我已经完成了我的作业,并研究了其他关于这个主题的答案,但没有一个解决了我的特定问题。

我想完全删除 io 库并部分删除 os 库(假设我只想保留 os.clock() 等函数)

我如何只通过 C API 实现这一点呢?

由于项目的性质,我不能修改 Lua 标头以及发送给我的脚本。这些不在我的控制范围之内。我唯一能够修改的就是解释器。

像这样做的事情:

lua_pushnil(state_pointer);
lua_setglobal(state_pointer, "os.execute");

并没有什么帮助,因为在脚本中用户可以调用 os=require('os') 并取回所有函数。

我不能禁用 require 函数,所以这使得事情变得更加困难。

有什么想法吗?

PS:更加好奇的是:如果我这样做:

luaopen_base(L);
luaopen_table(L);
luaopen_string(L);
luaopen_math(L);
luaopen_loadlib(L);(基本上是手动加载除osio之外的每个库)

而不是

luaL_openlibs(L);(这会加载所有库)

os=require('os') 或 io=require('io') 仍然有效吗?


@Nicol Bolas 不知道我是否做错了什么,但 os=require('os') 和 require('io') 会带回所有内容。

我的代码:

luaL_openlibs(LuaInstance);     /* load the libs        */
lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "io");
lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.execute");
lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.rename");
lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.remove");
lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.exit");

在我的脚本中,我只需要做一个

os = require('os')
io = require('io')

之后,os 函数和 io 函数都能正常工作,os.exit 仍然会关闭我的应用程序并且 io.write 也像往常一样工作。

原文链接 https://stackoverflow.com/questions/10108933

点赞
stackoverflow用户734069
stackoverflow用户734069

不会有太大的帮助,因为在脚本中,用户可以调用 os = require('os') 并获取所有函数返回值。

不,不会的。调用 require(os) 将简单地返回 os 表。你将有所更改的同一个表。所以没有问题。

所以只需在注册表后修改表。它会起作用,测试它非常容易。

注意: luaopen _ *不是常规的 C 函数。它们是 Lua C 函数; 它们是希望通过标准 Lua 机制调用的函数。你不能直接从 C 中调用它们。

在 Lua 5.1 中,你必须将它们推到堆栈上并使用 lua_pcall 或类似的调用函数来调用它们。在 Lua 5.2 中,你应该使用 luaL_requiref,它会将它们的表放入 Lua require 注册表中。


你的代码有两个问题。首先:

lua_setglobal(LuaInstance, "io");
lua_pushnil(LuaInstance);

这并不实际更改表。它只是删除表的引用。如果要更改表本身,则必须更改表。获取 io 表并修改它。遍历表并将其中每个值设置为 nil。仅替换名为 io 的全局变量的内容将不起作用。

但是,如果你要完全禁止使用 io,则不应首先注册它。

第二个问题是:

lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.execute");

这修改了键为 ["os.execute"] 的全局表的值。这相当于此 Lua 代码:

_G["os.execute"] = nil

这不等同于:

os.execute = nil;

当在 Lua 中使用 os.execute 时,这意味着取全局表( _G),找到名为 "os" 的键的值,并在从 "os" 获取的表中查找 "execute" 键。

当你使用 _G ["os.execute"] 时,你所说的是, 取全局表并查找名称为 "os.execute" 的键的值。

看到区别了吗?

你想要做的是获取存储在全局变量 os 中的表并修改该表。你不能使用 lua_setglobal,因为 os 表的成员不是全局变量。它们是表的成员。是的,存储它们的表碰巧是全局的。但是,你不能使用 lua_setglobal 修改存储在全局中的表的成员。

你必须这样做:

lua_getglobal(L, "os");
lua_pushnil(L);
lua_setfield(L, -2, "execute");
lua_pushnil(L);
lua_setfield(L, -2, "rename");
lua_pushnil(L);
lua_setfield(L, -2, "remove");
lua_pushnil(L);
lua_setfield(L, -2, "exit");
lua_pop(L, 1);
2012-04-11 15:50:24
stackoverflow用户596285
stackoverflow用户596285

我建议使用沙箱。请参见"如何创建安全的Lua沙箱"

对于require,请制作自己的包装器,在调用真实版本之前验证参数,并仅将包装器包含在沙箱中。

2012-04-11 17:37:01