lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Tim Hill once stated:
> 
> 
> > On Nov 27, 2018, at 3:04 PM, Sean Conner <sean@conman.org> wrote:
> > 
> >  So any code loaded via load() (or similar) will hvae _ENV as the first
> > upvalue, you can use setupvalue() to switch out the _ENV value currently
> > set.  Arbitrary functions might be a bit harder to locate the proper _ENV to
> > swap (if not outright impossible in some cases).
> 
> Sadly that’s not true. Any chunk that is COMPILED will honor this, but
> code that is obtained via string.dump() followed by load() often will not.
> Such a dumped function may or may not have _ENV as one of its upvalues,
> and even if it does, it may not be the first.

  I think there's a bug in the description for string.dump().  It states,
"[w]hen (re)loaded, those upvalues receive fresh instances containing nil."
But load() states "When you load a main chunk, the resulting function will
always have exactly one upvalue, the _ENV variable (see §2.2). However, when
you load a binary chunk created from a function (see string.dump), the
resulting function can have an arbitrary number of upvalues."

  Running this:

	local function upvals(name,f)
	  local function upv(i)
	    local n,v = debug.getupvalue(f,i)
	    if v then
	      print("",i,n,v)
	      return upv(i+1)
	    end
	  end
	  
	  print(name)
	  upv(1)
	end

	local a = 0
	local function foo(x)
	  a = a + 1
	  print(x)
	  print(os.getenv(x))
	  return a
	end

	upvals("foo",foo)

	local dumped = string.dump(foo)
	local reloaded = load(dumped)

	upvals("reloaded",reloaded)

  I get:

foo
        1       a       0
        2       _ENV    table: 0x89b5568
reloaded
        1       a       table: 0x89b5568

  So the first upvalue will have _ENV (in this case, the global _ENV), but
not the rest (also, the first upvalue for reloaded() should be a number, not
a table).

  -spc (Which presents yet another problem with simulating setfenv() in Lua
	5.2 or higher ... hmmm ... perhaps not a good idea after all)