我完成了我的作业并研究了关于这个主题的其他回复,但没有解决我的特定问题。
我想完全删除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像往常一样工作
答案 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
,在调用真实版本之前,创建自己的包装器来验证参数,并且只在沙箱中包含您的包装器。