3

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

我想完全删除 io 库,只删除部分操作系统(假设我想保留 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 照常工作

4

2 回答 2

7

不会有太大帮助,因为在脚本中用户可以调用 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,这会将他们的表放入 Luarequire注册表中。


您的代码有两个问题。第一的:

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

这实际上并没有改变表格。它只是删除了对表的引用。如果要更改表本身,则必须更改表。您必须获取io表格并对其进行修改。走动桌子并将其中的每个值设置为nil。简单地替换被调用的全局变量的内容io不会做任何事情。

但是,如果你想防止io被完全使用,你不应该一开始就注册它。

第二个问题是这样的:

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

这会修改全局表的值 who's key is ["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表的成员不是全局的;他们是一个表的成员。是的,它们存储的表恰好是一个全局表。但是您不能修改存储在全局中的表的成员 with 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-11T15:50:24.167 回答
3

我建议使用沙盒。请参阅“如何创建安全的 Lua 沙箱”

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

于 2012-04-11T17:37:01.430 回答