[libpeas] Prevent the accidental escaping of globals with Lua plugins
- From: Garrett Regier <gregier src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libpeas] Prevent the accidental escaping of globals with Lua plugins
- Date: Sat, 14 Feb 2015 20:29:42 +0000 (UTC)
commit 60cfc58eb64446fd3512f8c36b22a2f0b9968c9d
Author: Garrett Regier <garrettregier gmail com>
Date: Thu Jan 22 18:54:11 2015 -0800
Prevent the accidental escaping of globals with Lua plugins
This implements a strict mode which prevents the
creation of globals, except when using rawset().
This can be disabled for incompatible code by setting
__STRICT to false.
https://bugzilla.gnome.org/show_bug.cgi?id=742557
configure.ac | 1 +
loaders/lua5.1/Makefile.am | 18 ++----
loaders/lua5.1/peas-lua-internal.c | 48 +-------------
loaders/lua5.1/peas-lua-utils.c | 70 +++++++++++++++++++-
loaders/lua5.1/peas-lua-utils.h | 5 ++
loaders/lua5.1/peas-plugin-loader-lua.c | 3 +-
loaders/lua5.1/resources/Makefile.am | 13 ++++
.../lua5.1/{ => resources}/peas-lua-compile.lua | 0
.../lua5.1/{ => resources}/peas-lua-internal.lua | 2 +-
loaders/lua5.1/resources/peas-lua-strict.lua | 51 ++++++++++++++
.../lua5.1/{ => resources}/peas-lua.gresource.xml | 1 +
.../plugins/extension-lua/extension-lua51.lua | 21 ++++++
12 files changed, 172 insertions(+), 61 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 28d145f..e653301 100644
--- a/configure.ac
+++ b/configure.ac
@@ -541,6 +541,7 @@ libpeas/Makefile
libpeas-gtk/Makefile
loaders/Makefile
loaders/lua5.1/Makefile
+loaders/lua5.1/resources/Makefile
loaders/python/Makefile
loaders/python3/Makefile
data/Makefile
diff --git a/loaders/lua5.1/Makefile.am b/loaders/lua5.1/Makefile.am
index 6be90ea..49fe82f 100644
--- a/loaders/lua5.1/Makefile.am
+++ b/loaders/lua5.1/Makefile.am
@@ -1,5 +1,7 @@
# Lua 5.1 plugin loader
+SUBDIRS = resources
+
loaderdir = $(libdir)/libpeas-1.0/loaders
AM_CPPFLAGS = \
@@ -30,23 +32,15 @@ liblua51loader_la_LIBADD = \
$(PEAS_LIBS) \
$(LUA51_LIBS)
-%.luac: %.lua
- $(AM_V_GEN) $(LUA51_BIN) $(srcdir)/peas-lua-compile.lua $< $@
-
-all-local: peas-lua-internal.luac
-
-loader_resources_deps = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies
$(srcdir)/peas-lua.gresource.xml)
-peas-lua-resources.c: $(srcdir)/peas-lua.gresource.xml $(loader_resources_deps)
- $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --internal --target=$@ --sourcedir=$(srcdir) --generate-source
$(srcdir)/peas-lua.gresource.xml
+loader_resources_deps = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/resources
--generate-dependencies $(srcdir)/resources/peas-lua.gresource.xml)
+peas-lua-resources.c: $(srcdir)/resources/peas-lua.gresource.xml $(loader_resources_deps)
+ $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --internal --target=$@ --sourcedir=$(srcdir)/resources
--generate-source $(srcdir)/resources/peas-lua.gresource.xml
EXTRA_DIST = \
- peas-lua-compile.lua \
peas-lua.gresource.xml \
$(loader_resources_deps)
-CLEANFILES = \
- peas-lua-internal.luac \
- peas-lua-resources.c
+CLEANFILES = peas-lua-resources.c
gcov_sources = $(liblua51loader_la_SOURCES)
include $(top_srcdir)/Makefile.gcov
diff --git a/loaders/lua5.1/peas-lua-internal.c b/loaders/lua5.1/peas-lua-internal.c
index 23d2d6b..531bb17 100644
--- a/loaders/lua5.1/peas-lua-internal.c
+++ b/loaders/lua5.1/peas-lua-internal.c
@@ -25,10 +25,7 @@
#include "peas-lua-internal.h"
-#include <gio/gio.h>
-
#include <lauxlib.h>
-#include <lualib.h>
#include "peas-lua-utils.h"
@@ -60,54 +57,15 @@ failed_fn (lua_State *L)
gboolean
peas_lua_internal_setup (lua_State *L)
{
- GBytes *internal_lua;
- const gchar *code;
- gsize code_len;
-
- /* We don't use the byte-compiled Lua source
- * because glib-compile-resources cannot output
- * depends for generated files.
- *
- * There are also concerns that the bytecode is
- * not stable enough between different Lua versions.
- *
- * https://bugzilla.gnome.org/show_bug.cgi?id=673101
- */
- internal_lua = g_resources_lookup_data ("/org/gnome/libpeas/loaders/"
- "lua5.1/internal.lua",
- G_RESOURCE_LOOKUP_FLAGS_NONE,
- NULL);
- g_return_val_if_fail (internal_lua != NULL, FALSE);
-
- code = g_bytes_get_data (internal_lua, &code_len);
-
- /* Filenames are prefixed with '@' */
- if (luaL_loadbuffer (L, code, code_len, "@peas-lua-internal.lua") != 0)
- {
- g_warning ("Failed to load internal Lua code: %s",
- lua_tostring (L, -1));
-
- /* Pop error */
- lua_pop (L, 1);
- g_bytes_unref (internal_lua);
- return FALSE;
- }
-
- g_bytes_unref (internal_lua);
-
- if (!peas_lua_utils_call (L, 0, 1))
+ if (!peas_lua_utils_load_resource (L, "internal.lua", 0, 1))
{
- g_warning ("Failed to run internal Lua code: %s",
- lua_tostring (L, -1));
-
- /* Pop error */
- lua_pop (L, 1);
+ /* Already warned */
return FALSE;
}
if (!lua_istable (L, -1))
{
- g_warning ("Invalid result from internal Lua code: %s",
+ g_warning ("Invalid result from 'internal.lua' resource: %s",
lua_tostring (L, -1));
/* Pop result */
diff --git a/loaders/lua5.1/peas-lua-utils.c b/loaders/lua5.1/peas-lua-utils.c
index 76f7a9c..f22499a 100644
--- a/loaders/lua5.1/peas-lua-utils.c
+++ b/loaders/lua5.1/peas-lua-utils.c
@@ -25,10 +25,9 @@
#include "peas-lua-utils.h"
-#include <string.h>
+#include <gio/gio.h>
#include <lauxlib.h>
-#include <lualib.h>
gboolean
@@ -175,3 +174,70 @@ peas_lua_utils_call (lua_State *L,
lua_remove (L, -1 - (success ? n_results : 1));
return success;
}
+
+gboolean
+peas_lua_utils_load_resource (lua_State *L,
+ const gchar *name,
+ guint n_args,
+ guint n_results)
+{
+ gchar *resource_path;
+ GBytes *lua_resource;
+ const gchar *code;
+ gsize code_len;
+ gchar *lua_filename;
+
+ /* We don't use the byte-compiled Lua source
+ * because glib-compile-resources cannot output
+ * depends for generated files.
+ *
+ * There are also concerns that the bytecode is
+ * not stable enough between different Lua versions.
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=673101
+ */
+ resource_path = g_strconcat ("/org/gnome/libpeas/loaders/lua5.1/",
+ name, NULL);
+ lua_resource = g_resources_lookup_data (resource_path,
+ G_RESOURCE_LOOKUP_FLAGS_NONE,
+ NULL);
+ g_free (resource_path);
+
+ if (lua_resource == NULL)
+ {
+ g_warning ("Failed to find '%s' resource", name);
+ return FALSE;
+ }
+
+ code = g_bytes_get_data (lua_resource, &code_len);
+
+ /* Filenames are prefixed with '@' */
+ lua_filename = g_strconcat ("@peas-lua-", name, NULL);
+
+ if (luaL_loadbuffer (L, code, code_len, lua_filename) != 0)
+ {
+ g_warning ("Failed to load '%s' resource: %s",
+ name, lua_tostring (L, -1));
+
+ /* Pop error */
+ lua_pop (L, 1);
+ g_free (lua_filename);
+ g_bytes_unref (lua_resource);
+ return FALSE;
+ }
+
+ g_free (lua_filename);
+ g_bytes_unref (lua_resource);
+
+ if (!peas_lua_utils_call (L, n_args, n_results))
+ {
+ g_warning ("Failed to run '%s' resource: %s",
+ name, lua_tostring (L, -1));
+
+ /* Pop error */
+ lua_pop (L, 1);
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/loaders/lua5.1/peas-lua-utils.h b/loaders/lua5.1/peas-lua-utils.h
index 29069be..091f87d 100644
--- a/loaders/lua5.1/peas-lua-utils.h
+++ b/loaders/lua5.1/peas-lua-utils.h
@@ -40,6 +40,11 @@ gboolean peas_lua_utils_call (lua_State *L,
guint n_args,
guint n_results);
+gboolean peas_lua_utils_load_resource (lua_State *L,
+ const gchar *name,
+ guint n_args,
+ guint n_results);
+
G_END_DECLS
#endif /* __PEAS_LUA_UTILS_H__ */
diff --git a/loaders/lua5.1/peas-plugin-loader-lua.c b/loaders/lua5.1/peas-plugin-loader-lua.c
index 32c6418..ef07be3 100644
--- a/loaders/lua5.1/peas-plugin-loader-lua.c
+++ b/loaders/lua5.1/peas-plugin-loader-lua.c
@@ -285,7 +285,8 @@ peas_plugin_loader_lua_initialize (PeasPluginLoader *loader)
luaL_openlibs (L);
- if (!peas_lua_utils_require (L, "lgi") ||
+ if (!peas_lua_utils_load_resource (L, "strict.lua", 0, 0) ||
+ !peas_lua_utils_require (L, "lgi") ||
!peas_lua_utils_check_version (L,
LGI_MAJOR_VERSION,
LGI_MINOR_VERSION,
diff --git a/loaders/lua5.1/resources/Makefile.am b/loaders/lua5.1/resources/Makefile.am
new file mode 100644
index 0000000..710581e
--- /dev/null
+++ b/loaders/lua5.1/resources/Makefile.am
@@ -0,0 +1,13 @@
+LUAC_FILES = \
+ peas-lua-internal.luac \
+ peas-lua-strict.luac
+
+
+%.luac: %.lua
+ $(AM_V_GEN) $(LUA51_BIN) $(srcdir)/peas-lua-compile.lua $< $@
+
+all-local: $(LUAC_FILES)
+
+CLEANFILES = \
+ $(LUAC_FILES)
+
diff --git a/loaders/lua5.1/peas-lua-compile.lua b/loaders/lua5.1/resources/peas-lua-compile.lua
similarity index 100%
rename from loaders/lua5.1/peas-lua-compile.lua
rename to loaders/lua5.1/resources/peas-lua-compile.lua
diff --git a/loaders/lua5.1/peas-lua-internal.lua b/loaders/lua5.1/resources/peas-lua-internal.lua
similarity index 99%
rename from loaders/lua5.1/peas-lua-internal.lua
rename to loaders/lua5.1/resources/peas-lua-internal.lua
index 8f4e60d..f70904d 100644
--- a/loaders/lua5.1/peas-lua-internal.lua
+++ b/loaders/lua5.1/resources/peas-lua-internal.lua
@@ -159,4 +159,4 @@ end
return Hooks.new()
--- ex:set ts=4 et sw=4 ai:
+-- ex:ts=4:et:
diff --git a/loaders/lua5.1/resources/peas-lua-strict.lua b/loaders/lua5.1/resources/peas-lua-strict.lua
new file mode 100644
index 0000000..d3458b9
--- /dev/null
+++ b/loaders/lua5.1/resources/peas-lua-strict.lua
@@ -0,0 +1,51 @@
+--
+-- Copyright (C) 2015 - Garrett Regier
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU Library General Public License as published by
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU Library General Public License for more details.
+--
+-- You should have received a copy of the GNU Library General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor,
+-- Boston, MA 02110-1301, USA.
+--
+-- Modified version of: http://metalua.luaforge.net/src/lib/strict.lua.html
+
+__STRICT = true
+
+local mt = getmetatable(_G)
+if mt == nil then
+ mt = {}
+ setmetatable(_G, mt)
+end
+
+function mt:__newindex(name, value)
+ if __STRICT then
+ local what = debug.getinfo(2, 'S').what
+
+ if what ~= 'C' then
+ error("Attempted to create global variable '" ..
+ tostring(name) .. "'", 2)
+ end
+ end
+
+ rawset(self, name, value)
+end
+
+function mt:__index(name)
+ if not __STRICT or debug.getinfo(2, 'S').what == 'C' then
+ return rawget(self, name)
+ end
+
+ error("Attempted to access nonexistent " ..
+ "global variable '" .. tostring(name) .. "'", 2)
+end
+
+-- ex:ts=4:et:
diff --git a/loaders/lua5.1/peas-lua.gresource.xml b/loaders/lua5.1/resources/peas-lua.gresource.xml
similarity index 77%
rename from loaders/lua5.1/peas-lua.gresource.xml
rename to loaders/lua5.1/resources/peas-lua.gresource.xml
index 2eaf9cb..c8d43a0 100644
--- a/loaders/lua5.1/peas-lua.gresource.xml
+++ b/loaders/lua5.1/resources/peas-lua.gresource.xml
@@ -2,5 +2,6 @@
<gresources>
<gresource prefix="/org/gnome/libpeas/loaders/lua5.1">
<file alias="internal.lua">peas-lua-internal.lua</file>
+ <file alias="strict.lua">peas-lua-strict.lua</file>
</gresource>
</gresources>
diff --git a/tests/libpeas/plugins/extension-lua/extension-lua51.lua
b/tests/libpeas/plugins/extension-lua/extension-lua51.lua
index a0162fe..89cdf2d 100644
--- a/tests/libpeas/plugins/extension-lua/extension-lua51.lua
+++ b/tests/libpeas/plugins/extension-lua/extension-lua51.lua
@@ -80,6 +80,27 @@ function ExtensionLuaPlugin:do_call_multi_args(in_, inout)
return inout, in_
end
+-- Test strict mode
+local UNIQUE = {}
+
+local function assert_error(success, result)
+ assert(not success, result)
+end
+
+assert_error(pcall(function() _G[UNIQUE] = true end))
+assert(pcall(function()
+ rawset(_G, UNIQUE, true)
+ assert(_G[UNIQUE] == true)
+ _G[UNIQUE] = nil
+end))
+assert_error(pcall(function() _G[UNIQUE] = true end))
+assert(pcall(function()
+ __STRICT = false
+ _G[UNIQUE] = true
+ _G[UNIQUE] = nil
+ __STRICT = true
+end))
+
return { ExtensionLuaPlugin }
-- ex:set ts=4 et sw=4 ai:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]