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

时间:2012-04-11 15:19:47

标签: lua

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

我想完全删除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); (basically i'm loading every library by hand except os and io)

而不是

luaL_openlibs(L); (this loads all the libraries)

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像往常一样工作

2 个答案:

答案 0 :(得分:6)

  

无济于事,因为在脚本中用户可以调用os = require('os')并获取所有函数

不,它不会。调用require(os)只会返回os表。您将使用修改的相同表格。所以没有问题。

所以只需在注册后修改表格。它会起作用,测试它确实很容易。

  

luaopen_base(L);

建议: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"的键找到值并找到"execute"项在从"os"

获取的表格中

执行_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);

答案 1 :(得分:2)

我建议使用沙箱。请参阅"How to create a secure Lua sandbox"

对于require,在调用真实版本之前,创建自己的包装器来验证参数,并且只在沙箱中包含您的包装器。