lua-users home
lua-l archive

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


Title: RE: "Require" in a sandboxed environment


Okay, so my undestanding is WAY off.

Hmmm.  I really don't know why my first approach didn't work then.

I don't know if some example lua code will be of any help, as I think it will be more down to how the environments are implemented and communicate with each other, which is all in c++.

This is a really really simple example.

------------------------------------------------------------

module code in Utilities.lua

module(..., package.seeall)

g_var = nil

-------------------------------------------------------

code from environment 1:

utils = require "Utilities"

utils.g_var = 1
print(utils.g_var)

-----------------------------------------------------

code from environment 2:

utils = require "Utilities"

print(utils.g_var)

------------------------------------------------------------

We know that the environment 1 code is called before environment 2, yet the results are the ouput is:
1
nil

This example is probably an massive oversimplification of the situation we are in.  The environments are created like this:


static void CreateThread(State & state, State * host)
{
        if (m_MainState == NULL)
        {
                m_MainState = luaL_newstate();
                luaL_openlibs(m_MainState);
                lua_sethook(m_MainState, lineHook, LUA_MASKLINE, 0);
                // Create a table to store our references
                lua_pushstring(m_MainState, "lookup");
                lua_newtable(m_MainState);
                // Make it a weak table so that references are removed automatically by the garbage collection
                lua_pushstring(m_MainState, "__mode");
                lua_pushstring(m_MainState, "v");
                lua_settable(m_MainState, -3);
                // Add this table as an entry in the globals table
                lua_settable(m_MainState, LUA_GLOBALSINDEX);
        }

        lua_State * hostLuaState = host ? host->m_state : m_MainState;
        // Create the new thread
        state.m_state = lua_newthread(hostLuaState);
        lua_pushvalue(hostLuaState, -1); // Prevent the new thread from being garbage collected
        // Add to our list of registered states, keeping a reference to the state so we can remove it later on
        m_RegisteredStates.push_back(ThreadRef(&state, hostLuaState, luaL_ref(hostLuaState, LUA_REGISTRYINDEX)));
        // Create a local environment for this thread with a link to the global environment via __index metamethod
        lua_newtable(hostLuaState);
        lua_pushvalue(hostLuaState, -1);
        lua_setmetatable(hostLuaState, -2); // Set itself as a metatable
        lua_pushvalue(hostLuaState, LUA_GLOBALSINDEX);
        lua_setfield(hostLuaState, -2, "__index");
        lua_setfenv(hostLuaState, -2);
        lua_pop(hostLuaState, 1);

By way of an explanation:
The State class is a wrapper for a lua_State *, and I pass in a host state so that we can have a heirarchy of environments and "inherit" a parents globals.

In the lua code example given, env 1 and env 2 would both inherit a common host environment, which itself is a child of the main state. i.e.

main->host->env 1
                     ->env 2

(Apologies for the strange formatting of this email but we are having to use the MS Exchange Web client for our email at the moment!)


________________________________

From: lua-bounces@bazar2.conectiva.com.br [
mailto:lua-bounces@bazar2.conectiva.com.br] On Behalf Of Duncan Cross
Sent: 01 August 2007 12:16
To: Lua list
Subject: Re: "Require" in a sandboxed environment


On 8/1/07, Tom Miles <Tom@creative-assembly.co.uk> wrote:

                Now, my understanding of how modules work is that a module is loaded into a table, stored in a "packages" table, then a copy is also stored in the globals table of the enviornment it is loaded into, and another copy returned which can be stored in a differently named variable by the code calling require if desired.  As lua doesn't work with references, if the module has a variable within it, then there will now by potentially 3 different copies of this variable.


Nope, Lua DOES use references, all three will be references to the same table. It sounds like there is must be some other problem if you are requiring packages from several environments created from the same original main state and they all seem to be getting a new version each time, the package system uses the shared registry table. Do you have a simple example of one of the modules you are using?


DISCLAIMER
This email is sent by The Creative Assembly Limited company No. 03425917, registered in England & Wales registered office 27 Great West Road, Middlesex, TW8 9BW, England. The contents of this e-mail and any attachments are confidential to the intended recipient and may also be legally privileged. Unless you are the named addressee (or authorised to receive for the addressee) of this email you may not copy, disclose or distribute it to anyone else. If you have received this email in error, please notify us immediately by e-mail on
postmaster@creative-assembly.co.uk and then delete the email and any copies. The Creative Assembly Limited have made all reasonable efforts to ensure that this e-mail and any attached documents or software are free from software viruses, but it is the recipient's responsibility to confirm this.