Script attempted to create global variable

匿名 (未验证) 提交于 2019-12-03 01:48:02

问题:

I would like to load one script into redis that will export functions that future scripts executed will depend on, but attempt to define global function fails, same goes for global variables:

redis 127.0.0.1:6379> EVAL "function alex() return 3.1415 end" 0 (error) ERR Error running script (call to f_f24a5a054d91ccc74c2629e113f8f639bbedbfa2): user_script:1: Script attempted to create global variable 'alex' 

How can I define global functions and variables ?

回答1:

Looking at the source code in file scripting.c

/* This function installs metamethods in the global table _G that prevent  * the creation of globals accidentally.  *  * It should be the last to be called in the scripting engine initialization  * sequence, because it may interact with creation of globals. */ void scriptingEnableGlobalsProtection(lua_State *lua) {     char *s[32];     sds code = sdsempty();     int j = 0;      /* strict.lua from: http://metalua.luaforge.net/src/lib/strict.lua.html.      * Modified to be adapted to Redis. */     s[j++]="local mt = {}\n";     s[j++]="setmetatable(_G, mt)\n";     s[j++]="mt.__newindex = function (t, n, v)\n";     s[j++]="  if debug.getinfo(2) then\n";     s[j++]="    local w = debug.getinfo(2, \"S\").what\n";     s[j++]="    if w ~= \"main\" and w ~= \"C\" then\n";     s[j++]="      error(\"Script attempted to create global variable '\"..tostring(n)..\"'\", 2)\n";     s[j++]="    end\n";     s[j++]="  end\n";     s[j++]="  rawset(t, n, v)\n";     s[j++]="end\n";     s[j++]="mt.__index = function (t, n)\n";     s[j++]="  if debug.getinfo(2) and debug.getinfo(2, \"S\").what ~= \"C\" then\n";     s[j++]="    error(\"Script attempted to access unexisting global variable '\"..tostring(n)..\"'\", 2)\n";     s[j++]="  end\n";     s[j++]="  return rawget(t, n)\n";     s[j++]="end\n";     s[j++]=NULL;      for (j = 0; s[j] != NULL; j++) code = sdscatlen(code,s[j],strlen(s[j]));     luaL_loadbuffer(lua,code,sdslen(code),"@enable_strict_lua");     lua_pcall(lua,0,0,0);     sdsfree(code); } 

The doc-string of scriptingEnableGlobalsProtection indicates that intent is to notify script authors of common mistake (not using local).

It looks like this is not security feature, so we have two solutions:

One can remove this protection:

local mt = setmetatable(_G, nil) -- define global functions / variables function alex() return 3.1415 end -- return globals protection mechanizm setmetatable(_G, mt) 

Or use rawset:

local function alex() return 3.1415 end rawset(_G, "alex", alex) 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!