lua-users home
lua-l archive

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


Rici Lake <lua <at> ricilake.net> writes:

> Can a Lua program get at metatables (and environments)? A simple test 
> would demonstrate:
>  
>  ...
>  
> setmetatable("", {})
> stdin:1: bad argument #1 to 'setmetatable' (table expected, got string)

But setmetatable("", {}) always gives an error, even when
getmetatable("").__metatable is nil!

>  > -- now, let's get rid of the string table
>  > string = nil

While there are many approaches, it would be nice to leave as much of the
standard functionality in place as possible.  This example does just that;
all of the normal ways of accessing the string table (except for
table.foreach() and next() work identically):

-- Check all of the different ways of accessing the string table.
-- We only use string.rep, but all of the string functions will work.
function check_all()
    for i,v in ipairs {
        string.rep("foo",2),
        package.loaded.string.rep("foo",2),
        require("string").rep("foo",2),
        ("foo"):rep(2),
        getmetatable("").__index.rep("foo",2) }
    do assert( v == "foofoo" ) end
end

-- Make sure it works in the normal case
check_all()

-- We can update string.sub to be anything we want
assert( pcall( function() string.sub = string.sub end ) )

-- Make the string table a read-only proxy table
string = setmetatable( { },
    { __metatable="locked",
      __index=string,
      __newindex=function(t,k,v) error( "read only") end
    }
)

-- Update package.loaded to point to our new string table
package.loaded.string = string
assert( require"string" == string )

-- Update the shared metatable for strings
getmetatable("").__metatable = { __index = string }

-- string.sub is read only now
assert( not pcall( function() string.sub = string.sub end ) )

-- But all of the normal access methods still work
check_all()

The only remaining way to get to the string table is via
debug.getmetatable("").  But a sandbox shouldn't allow access
to the debug table anyway...

- Eric