--- C:/dev/luas/lua-5.2.0/src/lparser.c Fri Dec 2 05:23:56 2011 +++ C:/dev/luas/lua-5.2.0/src/lparser_safe.c Sun Mar 3 17:56:46 2013 @@ -306,6 +306,16 @@ } } +static void singlevar_from_string (LexState *ls, expdesc *var, TString *varname) { + FuncState *fs = ls->fs; + if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ + expdesc key; + singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ + lua_assert(var->k == VLOCAL || var->k == VUPVAL); + codestring(ls, &key, varname); /* key is variable name */ + luaK_indexed(fs, var, &key); /* env[varname] */ + } +} static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { FuncState *fs = ls->fs; @@ -571,6 +581,18 @@ L->top--; /* pop prototype (after possible collection) */ } +/* +** start the function with an implicit line: +** local _SAFE = _SAFE +*/ +static void safe_local(LexState * ls) { + expdesc v; + TString * safe = luaX_newstring ( ls, "_SAFE", 5); + singlevar_from_string(ls,&v,safe); + luaK_exp2nextreg(ls->fs,&v); + new_localvar(ls,safe); + adjustlocalvars(ls, 1); +} /* ** opens the main function, which is a regular vararg function with an @@ -582,6 +604,7 @@ fs->f->is_vararg = 1; /* main function is always vararg */ init_exp(&v, VLOCAL, 0); newupvalue(fs, ls->envn, &v); /* create environment upvalue */ + safe_local(ls); } @@ -909,6 +932,18 @@ prefixexp(ls, v); for (;;) { switch (ls->t.token) { + case '?': { /* safe navigation */ + expdesc safe; + luaX_next(ls); + enterlevel(ls); + luaK_infix(fs,OPR_OR,v); + if( singlevaraux(fs, luaX_newstring ( ls, "_SAFE", 5), &safe, 1) == VVOID) { + luaX_syntaxerror(ls, "the _SAFE upvalue is missing"); + } + luaK_posfix(fs, OPR_OR, v, &safe, line); + leavelevel(ls); + break; + } case '.': { /* fieldsel */ fieldsel(ls, v); break; --- C:/dev/luas/lua-5.2.0/src/lstate.c Mon Oct 3 10:54:25 2011 +++ C:/dev/luas/lua-5.2.0/src/lstate_safe.c Sun Mar 3 18:04:47 2013 @@ -224,6 +224,22 @@ luaM_free(L, l); } +/* Define the global _SAFE userdata. */ +static int _nullop(lua_State *L) {return 0;} +static int _nullitr(lua_State *L) { lua_pushcfunction(L,_nullop); return 1; } +static void register_safe(lua_State *L) { + lua_newuserdata(L,0); + lua_createtable(L,0,5); +#define nullmeta(fun) lua_pushcfunction(L,_nullop); lua_setfield(L,-2,fun); + lua_pushcfunction(L,_nullitr); lua_setfield(L,-2,"__pairs"); + lua_pushcfunction(L,_nullitr); lua_setfield(L,-2,"__ipairs"); + nullmeta("__index") + nullmeta("__newindex") + nullmeta("__call") +#undef nullmeta + lua_setmetatable(L,-2); + lua_setglobal(L,"_SAFE"); +} LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { int i; @@ -272,6 +288,7 @@ } else luai_userstateopen(L); + register_safe(L); return L; }