wplua: allow exchanging arguments and results with scripts

This commit is contained in:
George Kiagiadakis
2021-02-03 10:28:32 +02:00
parent ef9b6ef982
commit 460ff6591d
7 changed files with 82 additions and 38 deletions

View File

@@ -80,7 +80,7 @@ if SANDBOX_CONFIG["isolate_env"] then
-- store all of them in a global table so that they are not garbage collected
SANDBOX_ENV_LIST = {}
function sandbox(chunk)
function sandbox(chunk, ...)
-- chunk's environment will be an empty table with __index
-- to access our SANDBOX_ENV (without being able to write it)
local env = setmetatable({}, {
@@ -91,7 +91,7 @@ if SANDBOX_CONFIG["isolate_env"] then
-- set it as the chunk's 1st upvalue (__ENV)
debug.setupvalue(chunk, 1, env)
-- execute the chunk
chunk()
chunk(...)
end
else
-- in common_env mode, use the same environment for all loaded chunks
@@ -101,10 +101,10 @@ else
__index = SANDBOX_ENV,
})
function sandbox(chunk)
function sandbox(chunk, ...)
-- set it as the chunk's 1st upvalue (__ENV)
debug.setupvalue(chunk, 1, SANDBOX_COMMON_ENV)
-- execute the chunk
chunk()
chunk(...)
end
end

View File

@@ -129,7 +129,7 @@ wplua_enable_sandbox (lua_State * L, WpLuaSandboxFlags flags)
lua_settable (L, -3);
lua_setglobal (L, "SANDBOX_CONFIG");
if (!wplua_load_uri (L, URI_SANDBOX, &error)) {
if (!wplua_load_uri (L, URI_SANDBOX, 0, 0, &error)) {
wp_critical ("Failed to load sandbox: %s", error->message);
}
}
@@ -180,10 +180,11 @@ wplua_register_type_methods (lua_State * L, GType type,
static gboolean
_wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
const gchar * name, GError **error)
const gchar * name, int nargs, int nres, GError **error)
{
int ret;
int sandbox = 0;
int args_top = lua_gettop (L);
/* wrap with sandbox() if it's loaded */
if (lua_getglobal (L, "sandbox") == LUA_TFUNCTION)
@@ -195,11 +196,14 @@ _wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
if (ret != LUA_OK) {
g_set_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_COMPILATION,
"Failed to compile: %s", lua_tostring (L, -1));
lua_pop (L, sandbox + 1);
lua_pop (L, nargs + sandbox + 1);
return FALSE;
}
ret = _wplua_pcall (L, sandbox, 0);
/* push sandbox() and the chunk below the arguments */
lua_rotate (L, args_top, -nargs);
ret = _wplua_pcall (L, nargs + sandbox, nres);
if (ret != LUA_OK) {
g_set_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME,
"Runtime error while loading '%s'", name);
@@ -210,7 +214,8 @@ _wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
}
gboolean
wplua_load_buffer (lua_State * L, const gchar *buf, gsize size, GError **error)
wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
int nargs, int nres, GError **error)
{
g_return_val_if_fail (L != NULL, FALSE);
g_return_val_if_fail (buf != NULL, FALSE);
@@ -218,11 +223,12 @@ wplua_load_buffer (lua_State * L, const gchar *buf, gsize size, GError **error)
g_autofree gchar *name =
g_strdup_printf ("buffer@%p;size=%" G_GSIZE_FORMAT, buf, size);
return _wplua_load_buffer (L, buf, size, name, error);
return _wplua_load_buffer (L, buf, size, name, nargs, nres, error);
}
gboolean
wplua_load_uri (lua_State * L, const gchar *uri, GError **error)
wplua_load_uri (lua_State * L, const gchar *uri, int nargs, int nres,
GError **error)
{
g_autoptr (GFile) file = NULL;
g_autoptr (GBytes) bytes = NULL;
@@ -243,11 +249,12 @@ wplua_load_uri (lua_State * L, const gchar *uri, GError **error)
name = g_path_get_basename (uri);
data = g_bytes_get_data (bytes, &size);
return _wplua_load_buffer (L, data, size, name, error);
return _wplua_load_buffer (L, data, size, name, nargs, nres, error);
}
gboolean
wplua_load_path (lua_State * L, const gchar *path, GError **error)
wplua_load_path (lua_State * L, const gchar *path, int nargs, int nres,
GError **error)
{
g_autofree gchar *abs_path = NULL;
g_autofree gchar *uri = NULL;
@@ -263,5 +270,5 @@ wplua_load_path (lua_State * L, const gchar *path, GError **error)
if (!(uri = g_filename_to_uri (abs_path ? abs_path : path, NULL, error)))
return FALSE;
return wplua_load_uri (L, uri, error);
return wplua_load_uri (L, uri, nargs, nres, error);
}

View File

@@ -76,9 +76,11 @@ GVariant * wplua_table_to_asv (lua_State *L, int idx);
void wplua_asv_to_table (lua_State *L, GVariant *p);
gboolean wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
int nargs, int nres, GError **error);
gboolean wplua_load_uri (lua_State * L, const gchar *uri, int nargs, int nres,
GError **error);
gboolean wplua_load_path (lua_State * L, const gchar *path, int nargs, int nres,
GError **error);
gboolean wplua_load_uri (lua_State * L, const gchar *uri, GError **error);
gboolean wplua_load_path (lua_State * L, const gchar *path, GError **error);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(lua_State, wplua_free)

View File

@@ -79,7 +79,7 @@ wp_lua_scripting_plugin_enable (WpPlugin * plugin, WpTransition * transition)
/* execute scripts that were queued in for loading */
for (guint i = 0; i < self->scripts->len; i++) {
GError * error = NULL;
if (!wplua_load_path (self->L, g_ptr_array_index (self->scripts, i), &error)) {
if (!wplua_load_path (self->L, g_ptr_array_index (self->scripts, i), 0, 0, &error)) {
wp_transition_return_error (transition, error);
return;
}
@@ -163,7 +163,7 @@ wp_lua_scripting_plugin_load (WpComponentLoader * cl, const gchar * component,
/* keep in a list and delay loading until the plugin is enabled */
g_ptr_array_add (self->scripts, file);
return self->L ? wplua_load_path (self->L, file, error) : TRUE;
return self->L ? wplua_load_path (self->L, file, 0, 0, error) : TRUE;
}
/* interpret component as a configuration file */
else if (!g_strcmp0 (type, "config/lua")) {

View File

@@ -835,7 +835,7 @@ wp_lua_scripting_api_init (lua_State *L)
wplua_register_type_methods (L, WP_TYPE_SESSION_ITEM,
session_item_new, session_item_methods);
wplua_load_uri (L, URI_API, &error);
wplua_load_uri (L, URI_API, 0, 0, &error);
if (G_UNLIKELY (error))
wp_critical ("Failed to load api: %s", error->message);
}

View File

@@ -140,7 +140,7 @@ wp_lua_scripting_load_configuration (const gchar * conf_file,
path = g_build_filename (wp_get_config_dir (), conf_file, NULL);
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
wp_info ("loading config file: %s", path);
if (!wplua_load_path (L, path, error))
if (!wplua_load_path (L, path, 0, 0, error))
return FALSE;
found = TRUE;
}
@@ -160,7 +160,7 @@ wp_lua_scripting_load_configuration (const gchar * conf_file,
if (g_str_has_suffix (filename, ".lua")) {
g_autofree gchar * file = g_build_filename (path, filename, NULL);
wp_info ("loading config file: %s", file);
if (!wplua_load_path (L, file, error))
if (!wplua_load_path (L, file, 0, 0, error))
return FALSE;
found = TRUE;
}

View File

@@ -260,7 +260,7 @@ test_wplua_construct ()
const gchar code[] =
"o = TestObject_new()\n"
"assert (type(o) == 'userdata')\n";
wplua_load_buffer (L, code, sizeof (code) - 1, &error);
wplua_load_buffer (L, code, sizeof (code) - 1, 0, 0, &error);
g_assert_no_error (error);
g_assert_cmpint (lua_getglobal (L, "o"), ==, LUA_TUSERDATA);
@@ -293,7 +293,7 @@ test_wplua_properties ()
"o['test-float'] = 3.1415\n"
"o['test-double'] = 0.123456789\n"
"o['test-boolean'] = true\n";
wplua_load_buffer (L, code, sizeof (code) - 1, &error);
wplua_load_buffer (L, code, sizeof (code) - 1, 0, 0, &error);
g_assert_no_error (error);
g_assert_cmpint (lua_getglobal (L, "o"), ==, LUA_TUSERDATA);
@@ -318,7 +318,7 @@ test_wplua_properties ()
"assert (math.abs (o['test-float'] - 3.1415) < 0.00001)\n"
"assert (math.abs (o['test-double'] - 0.123456789) < 0.0000000001)\n"
"assert (o['test-boolean'] == true)\n";
wplua_load_buffer (L, code2, sizeof (code2) - 1, &error);
wplua_load_buffer (L, code2, sizeof (code2) - 1, 0, 0, &error);
g_assert_no_error (error);
wplua_free (L);
@@ -340,7 +340,7 @@ test_wplua_closure ()
" assert(s == expected_str)\n"
" f_was_called = true\n"
"end\n";
wplua_load_buffer (L, code, sizeof (code) - 1, &error);
wplua_load_buffer (L, code, sizeof (code) - 1, 0, 0, &error);
g_assert_no_error (error);
lua_getglobal (L, "f");
@@ -398,7 +398,7 @@ test_wplua_signals ()
"o['test-boolean'] = true\n"
"o:toggle()\n"
"assert(o['test-boolean'] == false)\n";
wplua_load_buffer (L, code, sizeof (code) - 1, &error);
wplua_load_buffer (L, code, sizeof (code) - 1, 0, 0, &error);
g_assert_no_error (error);
wplua_free (L);
}
@@ -417,14 +417,14 @@ test_wplua_sandbox_script ()
" Test = TestObject_new,\n"
" Table = { test = 'foobar' }\n"
"}\n";
wplua_load_buffer (L, code, sizeof (code) - 1, &error);
wplua_load_buffer (L, code, sizeof (code) - 1, 0, 0, &error);
g_assert_no_error (error);
wplua_enable_sandbox (L, WP_LUA_SANDBOX_ISOLATE_ENV);
const gchar code2[] =
"o = TestObject_new()\n";
wplua_load_buffer (L, code2, sizeof (code2) - 1, &error);
wplua_load_buffer (L, code2, sizeof (code2) - 1, 0, 0, &error);
g_debug ("expected error: %s", error ? error->message : "null");
g_assert_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME);
g_clear_error (&error);
@@ -432,31 +432,31 @@ test_wplua_sandbox_script ()
const gchar code3[] =
"o = Test()\n"
"o:toggle()\n";
wplua_load_buffer (L, code3, sizeof (code3) - 1, &error);
wplua_load_buffer (L, code3, sizeof (code3) - 1, 0, 0, &error);
g_assert_no_error (error);
const gchar code4[] =
"assert(string.len(Table.test) == 6)\n";
wplua_load_buffer (L, code4, sizeof (code4) - 1, &error);
wplua_load_buffer (L, code4, sizeof (code4) - 1, 0, 0, &error);
g_assert_no_error (error);
const gchar code5[] =
"o:call('change', 'by Lua', 55)\n";
wplua_load_buffer (L, code5, sizeof (code5) - 1, &error);
wplua_load_buffer (L, code5, sizeof (code5) - 1, 0, 0, &error);
g_debug ("expected error: %s", error ? error->message : "null");
g_assert_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME);
g_clear_error (&error);
const gchar code6[] =
"string.test = 'hello world'\n";
wplua_load_buffer (L, code6, sizeof (code6) - 1, &error);
wplua_load_buffer (L, code6, sizeof (code6) - 1, 0, 0, &error);
g_debug ("expected error: %s", error ? error->message : "null");
g_assert_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME);
g_clear_error (&error);
const gchar code7[] =
"Table.test = 'hello world'\n";
wplua_load_buffer (L, code7, sizeof (code7) - 1, &error);
wplua_load_buffer (L, code7, sizeof (code7) - 1, 0, 0, &error);
g_debug ("expected error: %s", error ? error->message : "null");
g_assert_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME);
g_clear_error (&error);
@@ -474,7 +474,7 @@ test_wplua_sandbox_config ()
const gchar code3[] =
"o = { answer = 42 }\n";
wplua_load_buffer (L, code3, sizeof (code3) - 1, &error);
wplua_load_buffer (L, code3, sizeof (code3) - 1, 0, 0, &error);
g_assert_no_error (error);
/* no assert() in minimal_std mode, resort to other means of failure */
@@ -482,13 +482,13 @@ test_wplua_sandbox_config ()
"if (o.answer ~= 42) then\n"
" non_existent_function()\n"
"end\n";
wplua_load_buffer (L, code4, sizeof (code4) - 1, &error);
wplua_load_buffer (L, code4, sizeof (code4) - 1, 0, 0, &error);
g_assert_no_error (error);
/* string.* is protected */
const gchar code6[] =
"string.test = 'hello world'\n";
wplua_load_buffer (L, code6, sizeof (code6) - 1, &error);
wplua_load_buffer (L, code6, sizeof (code6) - 1, 0, 0, &error);
g_debug ("expected error: %s", error ? error->message : "null");
g_assert_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME);
g_clear_error (&error);
@@ -496,7 +496,7 @@ test_wplua_sandbox_config ()
/* this would be an error if the assert function was exported, but it's not */
const gchar code7[] =
"assert = 'hello world'\n";
wplua_load_buffer (L, code7, sizeof (code7) - 1, &error);
wplua_load_buffer (L, code7, sizeof (code7) - 1, 0, 0, &error);
g_assert_no_error (error);
wplua_free (L);
@@ -524,7 +524,7 @@ test_wplua_convert_asv ()
"assert (math.abs (o['test-double'] - 3.14) < 0.0000000001)\n"
"assert (o['test-boolean'] == true)\n"
"assert (o['nested-table']['string'] == 'baz')\n";
wplua_load_buffer (L, code2, sizeof (code2) - 1, &error);
wplua_load_buffer (L, code2, sizeof (code2) - 1, 0, 0, &error);
g_assert_no_error (error);
lua_getglobal (L, "o");
@@ -558,6 +558,40 @@ test_wplua_convert_asv ()
wplua_free (L);
}
static void
test_wplua_script_arguments ()
{
g_autoptr (GError) error = NULL;
lua_State *L = wplua_new ();
g_autoptr (GVariant) v = g_variant_new_parsed ("@a{sv} { "
"'test-int': <42>, "
"'test-double': <3.14>, "
"'test-string': <'foobar'>, "
"'test-boolean': <true>, "
"'nested-table': <@a{sv} { 'string': <'baz'> }> "
"}");
wplua_asv_to_table (L, v);
const gchar code2[] =
"local o = ...\n"
"assert (o['test-string'] == 'foobar')\n"
"assert (o['test-int'] == 42)\n"
"assert (math.abs (o['test-double'] - 3.14) < 0.0000000001)\n"
"assert (o['test-boolean'] == true)\n"
"assert (o['nested-table']['string'] == 'baz')\n";
wplua_load_buffer (L, code2, sizeof (code2) - 1, 1, 0, &error);
g_assert_no_error (error);
/* same test, but with sandbox enabled */
wplua_enable_sandbox (L, WP_LUA_SANDBOX_ISOLATE_ENV);
wplua_asv_to_table (L, v);
wplua_load_buffer (L, code2, sizeof (code2) - 1, 1, 0, &error);
g_assert_no_error (error);
wplua_free (L);
}
gint
main (gint argc, gchar *argv[])
{
@@ -572,6 +606,7 @@ main (gint argc, gchar *argv[])
g_test_add_func ("/wplua/sandbox/script", test_wplua_sandbox_script);
g_test_add_func ("/wplua/sandbox/config", test_wplua_sandbox_config);
g_test_add_func ("/wplua/convert/asv", test_wplua_convert_asv);
g_test_add_func ("/wplua/script_arguments", test_wplua_script_arguments);
return g_test_run ();
}