在尝试并见证了将 Lua 和 LuaJIT 集成到我的游戏引擎中令人难以置信的轻松之后,我确信这就是我想要使用的脚本语言。我想将它用于我的 AI、单位描述、 map 触发器等。 (尽可能真的)。这个问题不仅适用于游戏开发,我可以想象创建一个可以加载外部脚本的脚本编辑器或窗口管理器(例如:带有 python 和包控制的崇高文本)
但现在我有一个难题:我真的很欣赏 的易用性。 LuaJIT FFI 提供绑定(bind)到我的引擎,但我 不想向 map 作者提供 FFI 的自由统治 例如。通过 FFI(当 JITted 时)进行 lua-to-c 调用的惊人速度也是我真正想要的。
所以理想情况下,我会编写自己的包装 Lua 文件,使用 FFI 绑定(bind)到我的引擎,并导出一个不错的模块供 map 作者和模组制作者使用。我的替代方法是编写一个 Vanilla lua 模块,这是可能的,但更麻烦和更慢。
编译 luajit 时我无法禁用 FFI,因为显然我想自己使用它,但我不知道如何在每个脚本或每个模块的基础上限制 FFI。显然,FFI 需要在我加载模块的 lua_State 中处于事件状态(之后我无法开始加载用户修改的脚本)。那我该怎么办?甚至可能吗?
编辑 :在我看来,理想的工作流程是:
注意 :我知道这仍然不是一个完美的(甚至是好的沙盒),正如 Mike Pall 在他的一些邮件中已经指出的那样,但我仍然不想让 map 作者访问 FFI。
最佳答案
也许我不明白这个问题,但如果你使用 a normal Lua sandbox无法访问 FFI,有什么问题?
例如:
ffi = require "ffi"
ffi.cdef([[int printf(const char *fmt, ...);]])
function say_hello()
ffi.C.printf("%s", "hello, ");
end
my_user_script = [[
say_hello()
ffi.C.printf("%s\n", "world")
]]
f = loadstring(my_user_script)
print("=== without sandbox ===")
print(pcall(f))
print("=== with sandbox ===")
setfenv(f,{say_hello = say_hello})
print(pcall(f))
这应该输出:
=== without sandbox ===
hello, world
true
=== with sandbox ===
hello, false [string "say_hello()..."]:2: attempt to index global 'ffi' (a nil value)
请注意,您还需要注意不要将 FFI cdata 泄漏到沙箱中。有a paragraph about this in the LuaJIT documentation .
关于security - 使用 LuaJIT 编写脚本并选择性地沙盒化 FFI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18376966/