|
Well, when I was talking about this in #lua on Freenode I imagined a scenario where someone would break out of a sandbox to get at debug.setmetatable() and then cause a segfault. I was just trying to get across the point that I'd rather have someone get at os.exit() than cause a segfault -- as you may have atexit() or on_exit() handlers or some other form of cleanup you want to happen. A segfault kind of prevents that..Anyway -- a lot of people seem to disagree with me that a segfault should be guarded against. I've heard arguments that asserting the type with checkudata() and also the size of the userdata before accessing members would make code inefficient -- and that my worries about people causing segfaults through the debug library are unfounded as you can just make all references to the debug library disappear, etc... Sean said earlier that that there are 0 uses of rawlen() or objlen() in Lua's core used for the sort of checking I was talking about -- I'm assuming he's advocating this because upstream doesn't do it? I still disagree but all of this is kind of disconnected from what I was talking about in my original posting.typedef union Udata {L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */struct {CommonHeader;struct Table *metatable;struct Table *env;size_t len; /* number of bytes */} uv;} Udata;Now you see, there are 2 fields/members in the userdata struct. One for the metatable and one for the environment. debug.setmetatable() sets the metatable pointer, not the env pointer. What I want is not easily possible without changing the definition of the Udata struct -- so I've given up on that since I like Roberto's idea to just contain all userdatas within one shared env table. :-) lua_get/setuservalue() set the env pointer, the Table pointer.Does anyone happen to know where else the env pointer is used? What other parts of Lua make use of it and why? I can't easily grep for 'env' and find out. Is this something historic from previous versions of Lua? I must be missing something obvious, but what is the env table on a userdata for? As far as I see it's simply for use with get/setuservalue(), to make a GC association. That's already very useful, but does it affect the use of the userdata elsewhere?On Tue, Dec 3, 2013 at 9:48 PM, David Heiko Kolf <david@dkolf.de> wrote:
Sir Pogsalot wrote:The only way for a script user to change the metatable for userdata
> Maybe this is just something that was drilled into me from a young
> age but I've always operated under the "libraries should never
> assert() or segfault" mindset. Also, users are sometimes directly
> scripting in Lua -- WoW, awesome window manager people, Garry's Mod,
> Android game creation apps/frameworks, etc... Sandboxed environments
> maybe, but still directly working with library functions. I don't
> think I'm being overzealous by calling this minimal amount of
> 'defensive programming' necessary :> Also lua_objlen() existed in
> 5.1 -- and it pains me daily to think how many libraries out there
> only luaL_checkudata() and blindly access members. Thanks for
> contributing to my early death :<
would be to use the debug library. The normal setmetatable function only
works on unprotected tables. And the debug library comes with this warning:
<http://www.lua.org/manual/5.2/manual.html#6.10>:
> You should exert care when using this library. Several of its
> functions violate basic assumptions about Lua code (e.g., that
> variables local to a function cannot be accessed from outside; that
> userdata metatables cannot be changed by Lua code; that Lua programs
> do not crash) and therefore can compromise otherwise secure code.
So for my modules I would use almost the same pattern as for the default
file module and just check the metatable. If somebody had taken this
metatable and used debug.setmetatable to put it on some different
userdata -- well, they would *want* their application to crash. I cannot
imagine how you would do this on accident. Executing foreign code is a
different matter, but it wouldn't make a lot of sense to expose the
debug module in a sandbox.
Best regards,
David Kolf