lua-users home
lua-l archive

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


PA wrote:
> function config( aPath )
>         local aChunck = setfenv( loadfile( aPath ), {} )
>         return getfenv( aChunck, aChunck() )
> end
> Thoughts?

I like this. The only drawback is that in operational code you will have
to catch any errors raised by loadfile(). It also makes config()
unusable after such an error...

It looks like setfenv() gets applied to config() when loadfile() fails,
returning nil. So setfenv() is applied to the wrong chunk. The manual
says that setfenv(0, t) sets the running thread's environment. It should
not apply if the first argument is nil.

Below is a transcript. Notice how getfenv(config) changes after the
syntax error. I believe this is bug in getfunc() in lbaselib.c (patch
and description in separate email).

rogers@rogers-~$ cat good.cfg
opt1=4
opt2=true
opt3='test string'
rogers@rogers-~$ cat bad.cfg
opt1=4
this is my song
-- not yours!
rogers@rogers-~$ lua
Lua 5.1.1  Copyright (C) 1994-2006 Lua.org, PUC-Rio
> function config( aPath )
>> local aChunck = setfenv( loadfile( aPath ), {} )
>> return getfenv( aChunck, aChunck() )
>> end
> s=config'good.cfg'
> for k,v in pairs(s) do print(k,v) end
opt3    test string
opt1    4
opt2    true
> print(s, config, getfenv(config), loadfile, _G)
table: 0x807efe8        function: 0x807f428     table: 0x806a450
function: 0x806b188     table: 0x806a450
> s=config'bad.cfg'
stdin:2: attempt to call global 'loadfile' (a nil value)
stack traceback:
        stdin:2: in function 'aChunck'
        stdin:3: in function 'config'
        stdin:1: in main chunk
        [C]: ?
> print(s, config, getfenv(config), loadfile, _G)
table: 0x807efe8        function: 0x807f428     table: 0x807e2e0
function: 0x806b188     table: 0x806a450
> s=config'good.cfg'
stdin:2: attempt to call global 'loadfile' (a nil value)
stack traceback:
        stdin:2: in function 'config'
        stdin:1: in main chunk
        [C]: ?
>

I've hacked the source quite a bit and I'm still not really sure why
this happens. It seems that lapi.c and lvm.c have the proper safeguards.
luaB_setfenv() checks lua_isnumber() on its first argument before
checking if it is zero.

If I do something clever like putting loadfile into the environment,
then it cannot find setfenv:

> t=getfenv(config)
> t.loadfile = loadfile
> s=config'/home/rogers/good.cfg'
stdin:2: attempt to call global 'setfenv' (a nil value)
stack traceback:
        stdin:2: in function 'config'
        stdin:1: in main chunk
        [C]: ?
>

It looks like getfunc() uses luaL_optint(L, 1, 1) when nil is at index
1, resulting in 1 for the level (default). I believe the code should
check for a numeric type first. I'll place a patch in a separate email.

Doug

-- 
Innovative Concepts, Inc. www.innocon.com 703-893-2007 x220