From 441943bd9b2bfd31c711211c4ec8503c7e67cd03 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Wed, 23 May 2012 16:51:59 +1000 Subject: [PATCH] Do not allow access to setfenv() and getfenv() by default Optionally remove setfenv and getfenv from the global environment in which user code runs. This will improve the forwards-compatibility of user code with Lua 5.2. Porting to Lua 5.2 would still be a daunting project, of questionable value, but at least only the internal code would need updating, and not thousands of on-wiki modules. Compared to the environment changes, the rest of the Lua 5.2 changes are relatively easy to simulate for backwards compatibility. Removed module() from the package module, since it depends on setfenv(). The native version of it is deprecated in Lua 5.2 for that reason. Change-Id: I978903ca98943ac941833da13fe5027949f6b429 --- Scribunto.php | 8 ++++++ engines/LuaCommon/LuaCommon.php | 3 ++- engines/LuaCommon/lualib/mw.lua | 16 ++++++++++-- engines/LuaCommon/lualib/package.lua | 26 +------------------ .../LuaSandbox/LuaSandboxEngineTest.php | 1 + .../LuaStandalone/LuaStandaloneEngineTest.php | 1 + 6 files changed, 27 insertions(+), 28 deletions(-) diff --git a/Scribunto.php b/Scribunto.php index e1ae3245..5f22d0ac 100644 --- a/Scribunto.php +++ b/Scribunto.php @@ -92,6 +92,13 @@ $wgScribuntoEngineConf = array( 'class' => 'Scribunto_LuaSandboxEngine', 'memoryLimit' => 50 * 1024 * 1024, 'cpuLimit' => 7, + + // Set this to true to allow setfenv() and getfenv() in user code. + // Note that these functions have been removed in Lua 5.2. Scribunto + // does not yet support Lua 5.2, but we expect support will be + // implemented in the future, and there is no guarantee that a + // simulation of setfenv() and getfenv() will be provided. + 'allowEnvFuncs' => false, ), 'luastandalone' => array( 'class' => 'Scribunto_LuaStandaloneEngine', @@ -105,6 +112,7 @@ $wgScribuntoEngineConf = array( 'luaPath' => null, 'memoryLimit' => 50 * 1024 * 1024, 'cpuLimit' => 7, + 'allowEnvFuncs' => false, ), ); diff --git a/engines/LuaCommon/LuaCommon.php b/engines/LuaCommon/LuaCommon.php index ffc3b641..0a6ec116 100644 --- a/engines/LuaCommon/LuaCommon.php +++ b/engines/LuaCommon/LuaCommon.php @@ -52,7 +52,8 @@ abstract class Scribunto_LuaEngine extends ScribuntoEngineBase { 'preprocess' => array( $this, 'preprocess' ), ) ); - $this->interpreter->callFunction( $this->mw['setup'] ); + $this->interpreter->callFunction( $this->mw['setup'], + array( 'allowEnvFuncs' => $this->options['allowEnvFuncs'] ) ); } /** diff --git a/engines/LuaCommon/lualib/mw.lua b/engines/LuaCommon/lualib/mw.lua index 57e90681..b576149b 100644 --- a/engines/LuaCommon/lualib/mw.lua +++ b/engines/LuaCommon/lualib/mw.lua @@ -4,6 +4,7 @@ local packageCache local packageModuleFunc local php local setupDone +local allowEnvFuncs = false --- Put an isolation-friendly package module into the specified environment -- table. The package module will have an empty cache, because caching of @@ -39,7 +40,7 @@ end --- Set up the base environment. The PHP host calls this function after any -- necessary host-side initialisation has been done. -function mw.setup() +function mw.setup( options ) if setupDone then return end @@ -56,6 +57,10 @@ function mw.setup() end end + if options.allowEnvFuncs then + allowEnvFuncs = true + end + -- Make mw_php private -- -- mw_php.loadPackage() returns function values with their environment @@ -108,7 +113,14 @@ end function mw.executeModule( chunk ) local env = mw.clone( _G ) makePackageModule( env ) - env.setfenv, env.getfenv = mw.makeProtectedEnvFuncs( {[_G] = true}, {} ) + + if allowEnvFuncs then + env.setfenv, env.getfenv = mw.makeProtectedEnvFuncs( {[_G] = true}, {} ) + else + env.setfenv = nil + env.getfenv = nil + end + setfenv( chunk, env ) return chunk() end diff --git a/engines/LuaCommon/lualib/package.lua b/engines/LuaCommon/lualib/package.lua index 799564b6..11d7efce 100644 --- a/engines/LuaCommon/lualib/package.lua +++ b/engines/LuaCommon/lualib/package.lua @@ -24,7 +24,7 @@ --]] -local assert, error, getfenv, ipairs, pairs, setfenv, setmetatable, type = assert, error, getfenv, ipairs, pairs, setfenv, setmetatable, type +local assert, error, ipairs, pairs, setmetatable, type = assert, error, ipairs, pairs, setmetatable, type local find, format, gfind, gsub, sub = string.find, string.format, string.gfind, string.gsub, string.sub -- @@ -135,27 +135,3 @@ function _PACKAGE.seeall (module) end meta.__index = _G end - - --- --- module function --- -function _G.module (modname, ...) - local ns = _LOADED[modname] - if type(ns) ~= "table" then - ns = findtable (_G, modname) - if not ns then - error (string.format ("name conflict for module '%s'", modname)) - end - _LOADED[modname] = ns - end - if not ns._NAME then - ns._NAME = modname - ns._M = ns - ns._PACKAGE = gsub (modname, "[^.]*$", "") - end - setfenv (2, ns) - for i, f in ipairs (...) do - f (ns) - end -end diff --git a/tests/engines/LuaSandbox/LuaSandboxEngineTest.php b/tests/engines/LuaSandbox/LuaSandboxEngineTest.php index 4bdb2006..79d8f2c1 100644 --- a/tests/engines/LuaSandbox/LuaSandboxEngineTest.php +++ b/tests/engines/LuaSandbox/LuaSandboxEngineTest.php @@ -7,6 +7,7 @@ class Scribunto_LuaSandboxEngineTest extends Scribunto_LuaEngineTest { var $stdOpts = array( 'memoryLimit' => 50000000, 'cpuLimit' => 30, + 'allowEnvFuncs' => true, ); function newEngine( $opts = array() ) { diff --git a/tests/engines/LuaStandalone/LuaStandaloneEngineTest.php b/tests/engines/LuaStandalone/LuaStandaloneEngineTest.php index 70eef317..67387934 100644 --- a/tests/engines/LuaStandalone/LuaStandaloneEngineTest.php +++ b/tests/engines/LuaStandalone/LuaStandaloneEngineTest.php @@ -9,6 +9,7 @@ class Scribunto_LuaStandaloneEngineTest extends Scribunto_LuaEngineTest { 'luaPath' => null, 'memoryLimit' => 50000000, 'cpuLimit' => 30, + 'allowEnvFuncs' => true, ); function newEngine( $opts = array() ) {