VEnv
Lua Virtual Environment

Installation

VEnv follows the package model for Lua 5.1, therefore this package should be "installed". Refer to Compat-5.1 configuration section about how to install the module properly.

Reference

VEnv provides a single function venv and offers an official way to bypass the virtual environment for those who need a more hibrid approach.

venv (func)
Creates a new environment and returns a function that executes the passed function func inside the new environment.
The Virtual Environment provided by venv() automatically inherits any global variables from the calling environment, but protects the calling environment against modifications. This is achieved by creating a copy of any external value accessed from inside the new environment on demand. After the first access, the copy will be used instead of the inherited value. Also, care is taken to avoid that an assignment to nil implies in the use of the original behavior. In this case the value is maintained as nil.

Stable

Stable is the official way to bypass the virtual environment created by venv(). It implements a Lua state persistent table by offering functions to get, set and iterate over its attributes. The module must be "required" outside the virtual environment to be used inside it.

stable.get (key)
Returns the value of a given key.
stable.pairs ()
Iterates over every Stable key just like Lua pairs() do.
stable.set (key, value)
Stores a value associated to a key. Returns nothing.

Examples

Suppose you need to allow the execution of user files but in way that these files can not compromise your system and can not use some functions such as os.execute.

The following example shows how a file like script.lua:

x = "inside"
assert((x == "inside"),
       "Error setting/accessing variable x inside VEnv", x)
assert((os.execute == nil),
       "os.execute should not be allowed")
var = 1

can be executed inside a Virtual Environment in a protected way:

require"venv"
t1 = { t2 = { t3 = "ok" } }
x = "outside"

function risky()
    assert ((t1.t2.t3 == "ok"),
            "error accessing multi-indexed variable")
    os.execute = nil
    loadfile ("script.lua")()
end

local prot = venv (risky)
prot ()
assert ((x == "outside"),
        "variable x modified by VEnv!")
assert ((var == nil),
        "VEnv modified external environment!")
assert ((os.execute ~= nil),
        "VEnv modified external environment!")

Running the above code should report no errors, since VEnv will garantee that:

  • Inside function risky the access to t1.t2.t3 is granted.
  • After the call to prot (the protected version of risky) the values of x, var and os.execute are the same as before the call.

But what if the user scripts needs to maintain values for the next invokations? In those cases you can use Stable to save the values and recover them in a latter time:

if stable.get("my value") then
    x = stable.get("my value")
else
    stable.set("my value", "inside")
end

assert((x == "inside"),
       "Error setting/accessing variable x inside VEnv", x)
assert((os.execute == nil),
       "os.execute should not be allowed")
var = 1

When using Stable it is good practice to use some key name formation rule to avoid key name clashing. Also keep in mind that any Stable key and its value are accesible by everyone so this may pose some security issues.

To offer Stable to the user scripts, the module responsible for the venv call should require"stable" before require"venv".

Valid XHTML 1.0!

$Id: manual.html,v 1.6 2005/07/08 19:22:37 carregal Exp $