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

FMM*_*rel 3 lua

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

我想完全删除io库和os只是部分(让我们说我想保留os.clock()和其他)

我怎样才能从C API中实现这一点.

由于项目的性质,我不允许修改Lua标头和将发送给我的脚本.这些不在我的控制之下.我唯一可以修改的是解释器.

做这样的事情:

lua_pushnil(state_pointer);
lua_setglobal(state_pointer, "os.execute");
Run Code Online (Sandbox Code Playgroud)

没有多大帮助,因为在脚本中用户可以调用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)
Run Code Online (Sandbox Code Playgroud)

代替

luaL_openlibs(L); (this loads all the libraries)
Run Code Online (Sandbox Code Playgroud)

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");
Run Code Online (Sandbox Code Playgroud)

在我的脚本中,我只是做了一个

os = require('os')
io = require('io')
Run Code Online (Sandbox Code Playgroud)

在此os函数和io函数之后所有工作.os.exit仍然关闭我的应用程序,io.write像往常一样工作

Nic*_*las 5

没有多大帮助,因为在脚本中用户可以调用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);
Run Code Online (Sandbox Code Playgroud)

这实际上并没有改变表格.它只是删除对表的引用.如果要更改表本身,则必须更改表.你必须得到io表并修改它.走桌子并将其中的每个值都设置为nil.简单地替换所调用的全局变量的内容io将不起作用.

但是,如果要防止io完全使用,则不应将其注册为开头.

第二个问题是:

lua_pushnil(LuaInstance);
lua_setglobal(LuaInstance, "os.execute");
Run Code Online (Sandbox Code Playgroud)

这会修改键的全局表的值["os.execute"].它相当于这个Lua代码:

_G["os.execute"] = nil
Run Code Online (Sandbox Code Playgroud)

这是一样的:

os.execute = nil;
Run Code Online (Sandbox Code Playgroud)

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

当你这样做时_G["os.execute"],你所说的是获取全局表并使用名为key的值查找值"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);
Run Code Online (Sandbox Code Playgroud)