Remove windows line endings (I don't understand how they got here in the first place...)
[vlc.git] / share / luaintf / modules / sandbox.lua
1 --[==========================================================================[
2  sandbox.lua: Lua sandboxing facilities
3 --[==========================================================================[
4  Copyright (C) 2007 the VideoLAN team
5  $Id$
6
7  Authors: Antoine Cellerier <dionoea at videolan dot org>
8
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 --]==========================================================================]
23
24 module("sandbox",package.seeall)
25
26 -- See Programming in Lua (second edition) for sandbox examples
27 -- See http://lua-users.org/wiki/SandBoxes for a list of SAFE/UNSAFE variables
28
29 local sandbox_blacklist = {
30     collectgarbage = true,
31     dofile = true,
32     _G = true,
33     getfenv = true,
34     getmetatable = true,
35     load = true, -- Can be protected I guess
36     loadfile = true, -- Can be protected I guess
37     loadstring = true, -- Can be protected I guess
38     rawequal = true,
39     rawget = true,
40     rawset = true,
41     setfenv = true,
42     setmetatable = true,
43     module = true,
44     require = true,
45     package = true,
46     debug = true,
47 }
48
49 function readonly_table_proxy(name,src,blacklist)
50     if type(src)=="nil" then return end
51     if type(src)~="table" then error("2nd argument must be a table (or nil)") end
52     local name = name
53     local t = src
54     local blist = {}
55     if blacklist then
56         for _, v in pairs(blacklist) do
57             blist[v] = true
58         end
59     end
60     local metatable_readonly = {
61         __index = function(self,key)
62             if blist[key] then
63                 error("Sandbox: Access to `"..name.."."..key.."' is forbidden.")
64             end
65             return t[key]
66         end,
67         __newindex = function(self,key,value)
68             error("It is forbidden to modify elements of this table.")
69         end,
70     }
71     return setmetatable({},metatable_readonly)
72 end
73
74 -- Of course, all of this is useless if the sandbox calling code has
75 -- another reference to one of these tables in his global environement.
76 local sandbox_proxy = {
77     coroutine   = readonly_table_proxy("coroutine",coroutine),
78     string      = readonly_table_proxy("string",string,{"dump"}),
79     table       = readonly_table_proxy("table",table),
80     math        = readonly_table_proxy("math",math),
81     io          = readonly_table_proxy("io",io),
82     os          = readonly_table_proxy("os",os,{"exit","getenv","remove",
83                                                 "rename","setlocale"}),
84     sandbox     = readonly_table_proxy("sandbox",sandbox),
85 }
86
87 function sandbox(func,override)
88     local _G = getfenv(2)
89     local override = override or {}
90     local sandbox_metatable =
91     {
92         __index = function(self,key)
93             if override[key] then
94                 return override[key]
95             end
96             if sandbox_blacklist[key] then
97                 error( "Sandbox: Access to `"..key.."' is forbidden." )
98             end
99             --print(key,"not found in env. Looking in sandbox_proxy and _G")
100             local value = sandbox_proxy[key] or _G[key]
101             rawset(self,key,value) -- Keep a local copy
102             return value
103         end,
104         __newindex = function(self,key,value)
105             if override and override[key] then
106                 error( "Sandbox: Variable `"..key.."' is read only." )
107             end
108             return rawset(self,key,value)
109         end,
110     }
111     local sandbox_env = setmetatable({},sandbox_metatable)
112     return function(...)
113         setfenv(func,sandbox_env)
114         local ret = {func(...)} -- Not perfect (if func returns nil before
115                                 -- another return value) ... but it's better
116                                 -- than nothing
117         setfenv(func,_G)
118         return unpack(ret)
119     end
120 end