Lua脚本语言十分强大,但是有一个问题就是全局可写,比如你定义一个全局变量很容易不小心被另一个同名变量给覆盖掉。
这种问题一旦出现是十分难以调查的,该文章介绍的这种机制可以解决该问题。
我已经在我自己的工程中应用了该技术,它可以达到以下目的:
1.全局变量不能直接在Lua中被修改
2.可以创建出不能直接被修改的table
3.屏蔽一些你不想开放的Lua原生函数比如文件操作
注:我是混合着使用C和Lua实现该机制的,但是在纯Lua里也可以同样实现。为了便于表述,我这里只给出纯Lua版的例子。
另外该范例代码仅限于Lua 5.2版,但是该技巧同样可以适用于其他版本,但可能需要修改该一部分代码。
首先将所有安全机制的代码放进一个Lua脚本文件safe.lua如下:
-- 仅支持Lua 5.2版
assert(_VERSION == "Lua 5.2")
-- 全局环境在注册表中的索引值(见lua.h)
local LUA_RIDX_GLOBALS = 2
-- 安全table的metatable标志
local SAFE_TABLE_FLAG = ".SAFETABLE"
-- 设置全局安全保护机制
local function SetupGlobal()
-- 获取注册表
local reg = debug.getregistry()
local env = {} -- 新环境table
local proxy = {} -- 代理table
local mt = {} -- metatable
-- 操作重载
mt.__index = proxy
mt.__newindex = function() print("cannot modify global enviroment!") end
mt.__len = function() return #proxy end
mt.__pairs = function() return pairs(proxy) end
mt.__ipairs = function() return ipairs(proxy) end
-- 隐藏metatable
mt.__metatable = 0
-- 标记为安全table
mt[SAFE_TABLE_FLAG] = true
-- 获取旧环境
local old_env &#