Skip to content

A wrapper around the luaSandbox extension with batteries included.

Notifications You must be signed in to change notification settings

cineman/silicon

Repository files navigation

Silicon

Hydrogen CI

Wrapper around the luaSandbox extension for Hydrogen.

Usage

Silicon is built to be used with the ClanCats/Container which hydrogen is built around.

Running the examples

There is a simple bash script to run the examples through docker in case luaSandbox is not installed locally.

$ bash run-example.sh ./examples/01_simple_eval.php

Setup

First bind the runner to the container:

@silicon.runner: @silicon
@silicon: Silicon\SiliconRunner(@container)
    - setDefaultPreloadCache(@silicon.cache)

@silicon.cache: Silicon\SiliconPreloadCache(:const.PATH_CACHE)

In most cases you want to use a preload cache, this will dump all lua code from available modules in binary form to disk. Which improves initialization time for each sandbox. This is optional so feel free to leave that out. Note: If you are not using the hydrogen framework, you need to use an actual path instead of :const.PATH_CACHE

Running lua code

Now you can use the silicon runner create a sandbox and run some lua code in it.

$silicon = $container->get('silicon');
$context = $silicon->boot();

$result = $context->eval(<<<'LUA'
function distance(x1, y1, x2, y2)
    local dx = x1 - x2
    local dy = y1 - y2
    return math.sqrt(dx * dx + dy * dy)
end

return distance(10, 5, 50, 100)
LUA);

var_dump($result); // float(103.07764064044152)

The function distance has been declared in our lua context now, so we can also directly call it:

$result = $context->invokeFunction('distance', 5, 5, 10, 10);
var_dump($result); // float(7.0710678118654755)

Sandbox constraints

When booting up a Sandbox you can pass execution constraints to ensure no resource exhaustion.

$silicon = $container->get('silicon');

$options = new LuaContextOptions;
$options->memoryLimit = LuaContextOptions::MEML_32MB;
$options->CPUTimeLimit = 30.0; // 30 seconds

$context = $silicon->boot($options);

Console

Silicon comes with a console built in for simpler debugging and realtime feedback:

console.log(42) 
console.warn("noooo")
console.error({'Something', 'Went', 'Wrong'})

Output:

// int(42)
// string("noooo")
// [3]{
//   1: string("Something")
//   2: string("Went")
//   3: string("Wrong")
// }
foreach($context->console()->all() as $message) {
    echo $message[1] . PHP_EOL;
}

Defining custom modules

To define a custom module it needs to be bound to the container which is passed to runner or the sandbox itself, here an example how you create a email module with sendmail. (Obviously do not do this!)

@my_lua_mailer: App\LuaMailer
    = silicon.module: 'email'

All you have to do is to implement the SiliconModuleInterface:

class LuaMailer implements SiliconModuleInterface
{
    public function getExposedFunctions(LuaContext $ctx) : ?array {
        return [
            'send' => [$this, 'exposeSend']
        ];
    }

    public function preloadLua() : ?string {
        return null;
    }

    public function exposeSend(string $to, string $subject, string $message) {
        mail($to, $subject, $message . '\n\nSend from Lua!');
    }
}

In lua you will be able to use that module as follows:

local to = '[email protected]'
local subject = 'Please dont spam us'
local message = 'Hello there'

email.send(to, subject, message)

About

A wrapper around the luaSandbox extension with batteries included.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages