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 byvenv()
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 tonil
implies in the use of the original behavior. In this case the value is maintained asnil
.
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 tot1.t2.t3
is granted. - After the call to
prot
(the protected version ofrisky
) the values ofx
,var
andos.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"
.