Isn't load() in 5.2 too naive about _ENV?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Isn't load() in 5.2 too naive about _ENV?

Artur Galyamov
Why does load(...) in 5.2 make an assumption, that _ENV is *always*
first upvalue? I think it should search for the name "_ENV" instead
(and set nothing, if not found).

------------------------------------------------------------
local upvalue

function test()
    return upvalue, global
end

assert(debug.getupvalue(test, 1) == "upvalue")
assert(debug.getupvalue(test, 2) == "_ENV")

local f = load(string.dump(test), nil, nil, "environment")
-- bad thing happened...

print(debug.getupvalue(f, 1)) -- "upvalue", "environment"
print(debug.getupvalue(f, 2)) -- "_ENV", nil
------------------------------------------------------------

-- Artur

Reply | Threaded
Open this post in threaded view
|

Re: Isn't load() in 5.2 too naive about _ENV?

Luiz Henrique de Figueiredo
> Why does load(...) in 5.2 make an assumption, that _ENV is *always*
> first upvalue? I think it should search for the name "_ENV" instead
> (and set nothing, if not found).

Upvalue names may not be available of debug information has been stripped.

Reply | Threaded
Open this post in threaded view
|

Re: Isn't load() in 5.2 too naive about _ENV?

Artur Galyamov
05.10.2011, 14:27, "Luiz Henrique de Figueiredo" <[hidden email]>:
>>  Why does load(...) in 5.2 make an assumption, that _ENV is *always*
>>  first upvalue? I think it should search for the name "_ENV" instead
>>  (and set nothing, if not found).
>
> Upvalue names may not be available of debug information has been stripped.

Aww, thanks.. I didn't know about stripping.

So, please correct me, if I am wrong. To properly change environment
of Lua function, that function should in general follow "_ENV is first
upvalue" protocol. This is only guaranteed for newly compiled chunks,
i.e. load() with source string argument, and not for string.dump'ed or
other arbitrary chunks.

-- Artur

Reply | Threaded
Open this post in threaded view
|

Re: Isn't load() in 5.2 too naive about _ENV?

Luiz Henrique de Figueiredo
> So, please correct me, if I am wrong. To properly change environment
> of Lua function, that function should in general follow "_ENV is first
> upvalue" protocol. This is only guaranteed for newly compiled chunks,
> i.e. load() with source string argument, and not for string.dump'ed or
> other arbitrary chunks.

Right. Only for "main" chunks, not arbitrary functions.

Reply | Threaded
Open this post in threaded view
|

Re: Isn't load() in 5.2 too naive about _ENV?

Peng Zhicheng
In reply to this post by Artur Galyamov
于 2011-10-5 23:03, Artur Galyamov 写道:
> 05.10.2011, 14:27, "Luiz Henrique de Figueiredo"<[hidden email]>:
> To properly change environment of Lua function, that function should in general follow "_ENV is first upvalue" protocol. This is only guaranteed for newly compiled chunks, i.e. load() with source string argument, and not for string.dump'ed or other arbitrary chunks. -- Artur
Lua 5.2 has changed the semantic of the "global namespace", there is no longer a dedicated fenv table, but the first upvalue instead.
the `_ENV' identifier is just the **DEFAULT** lexical name for the "first upvalue", so it is meaningful only at compile time. when a chunk is compiled,
all access to global names are looked up in the first upvalue, the identifier `_ENV' would just be in the debug data to represent the `name' of
the first upvalue, which could be totally stripped out.

in fact, you may change this in luaconf.h when you config and build Lua 5.2, or even at runtime from C, see LexState.


Reply | Threaded
Open this post in threaded view
|

Re: Isn't load() in 5.2 too naive about _ENV?

Artur Galyamov
>>  To properly change environment of Lua function, that function should in general follow "_ENV is first upvalue" protocol. This is only guaranteed for newly compiled chunks, i.e. load() with source string argument, and not for string.dump'ed or other arbitrary chunks. -- Artur
>
> Lua 5.2 has changed the semantic of the "global namespace", there is no longer a dedicated fenv table, but the first upvalue instead.
> the `_ENV' identifier is just the **DEFAULT** lexical name for the "first upvalue", so it is meaningful only at compile time. when a chunk is compiled,
> all access to global names are looked up in the first upvalue, the identifier `_ENV' would just be in the debug data to represent the `name' of
> the first upvalue, which could be totally stripped out.
>
> in fact, you may change this in luaconf.h when you config and build Lua 5.2, or even at runtime from C, see LexState.

I thought so, but _ENV is not always first:

----------------------------------------------------
local a
function test()
    return a, b -- upvalue[1]="a", upvalue[2]="_ENV"
end
----------------------------------------------------

_ENV is to function what default gateway is to network station. In
abstract thinking, there is no _ENV, right. But in field of sandbox
programming, _ENV is  *the* conception. I'm wondering why we lost
control over arbitrary chunk's environment with 5.2.

load(...)-ed text sources are still ok, will use them instead.

-- Artur

Reply | Threaded
Open this post in threaded view
|

Re: Isn't load() in 5.2 too naive about _ENV?

Roberto Ierusalimschy
> [...] I'm wondering why we lost
> control over arbitrary chunk's environment with 5.2.

If I understood you correctly, this point has been discussed several
times in this list. The old 'setfenv' mechanism is "too powerful", as
it breaks the basic abstraction mechanism of functions.

To set the environment of another function is akin to accessing its
upvalues, something better provided by the debug library.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Isn't load() in 5.2 too naive about _ENV?

Roberto Ierusalimschy
In reply to this post by Artur Galyamov
> _ENV is to function what default gateway is to network station. In
> abstract thinking, there is no _ENV, right. But in field of sandbox
> programming, _ENV is  *the* conception.

I beg to differ. _ENV is irrelevant for sandbox programming, as it is
only a compiler trick. Whatever you can do with _ENV you can do without
it.

What is very relevant to sandboxing is the behavior of 'load', as it
offers the global environment to the function being loaded. (From a
security point of view, it is irrelevant whether this global environment
is being set to _ENV or any other upvalue.) So, as you said, sandboxes
should not use 'load' without an explicit env argument (or without a
'mode' argument).

What is also very relevant to sandboxing is whether we can change the
behavior of a function without using the debug library.

-- Roberto


Reply | Threaded
Open this post in threaded view
|

Re: Isn't load() in 5.2 too naive about _ENV?

Artur Galyamov
In reply to this post by Roberto Ierusalimschy
> If I understood you correctly, this point has been discussed several
> times in this list. The old 'setfenv' mechanism is "too powerful", as
> it breaks the basic abstraction mechanism of functions.

Sorry, I have missed these threads... Here they are:

http://lua-users.org/lists/lua-l/2011-05/msg00191.html
http://lua-users.org/lists/lua-l/2011-05/msg00115.html
http://lua-users.org/lists/lua-l/2011-03/msg01157.html

I think I get it now :) Thank you all for the information!

-- Artur