-
-
Notifications
You must be signed in to change notification settings - Fork 13
/
sandbox.lua
150 lines (133 loc) · 3.66 KB
/
sandbox.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
-- Lua sandboxing
-- Part of Live Simulator: 2
-- See copyright notice in main.lua
-- Should I told you that sandbox is slow!!!
local Luaoop = require("libs.Luaoop")
local utf8 = require("utf8")
local Util = require("util")
local sandbox = Luaoop.class("Livesim2.Sandbox")
function sandbox:__construct()
local internal = Luaoop.class.data(self)
-- Module sandboxing (blacklist method)
local stringModule = Util.deepCopy(string)
stringModule.dump = nil
-- Modules that is loaded
internal.loadedModules = {
coroutine = Util.deepCopy(coroutine),
math = Util.deepCopy(math),
os = {
difftime = os.difftime,
time = os.time,
date = os.date,
clock = os.clock
},
string = stringModule,
table = Util.deepCopy(table),
utf8 = Util.deepCopy(utf8),
}
if bit then
internal.loadedModules.bit = Util.deepCopy(bit)
end
-- Require function handlers
-- Must return status (true if module loaded) plus module value
internal.requireHandlers = {}
-- Require function preloads
internal.requirePreload = {}
-- Metatable that shouldn't be returned
internal.restrictedMetatable = {
getmetatable("") -- string metatable
}
-- Setup Lua environment
internal.env = {
assert = assert,
error = error,
getmetatable = function(t)
local v = getmetatable(t)
for i = 1, #internal.restrictedMetatable do
if internal.restrictedMetatable[i] == v then
error("attempt to getmetatable of protected data")
end
end
return v
end,
ipairs = ipairs,
loadstring = function(f, name)
local r, msg = loadstring(f, name)
if r then
setfenv(r, internal.env)
end
return r, msg
end,
next = next,
pairs = pairs,
pcall = pcall,
print = print,
rawget = rawget,
rawset = rawset,
rawequal = rawequal,
require = function(name)
if internal.loadedModules[name] then
return internal.loadedModules[name]
elseif internal.requirePreload[name] then
local module = internal.requirePreload[name](name) or true
internal.loadedModules[name] = module
return module
else
-- call handlers
for i = 1, #internal.requireHandlers do
local status, module = internal.requireHandlers[i](name)
if status then
module = module or true
internal.loadedModules[name] = module
return module
end
end
error("module '"..name.."' not found")
end
end,
setmetatable = setmetatable,
tonumber = tonumber,
tostring = tostring,
type = type,
unpack = unpack,
_VERSION = _VERSION,
xpcall = xpcall,
}
internal.env._G = internal.env
for k, v in pairs(internal.loadedModules) do
internal.env[k] = v
end
end
local _temporarySelf
local function _runWrap()
return _temporarySelf.tempFunc(unpack(_temporarySelf.tempArg))
end
function sandbox:run(func, ...)
local internal = Luaoop.class.data(self)
setfenv(func, internal.env)
self.tempFunc = func
self.tempArg = {...}
_temporarySelf = self
local out = {xpcall(_runWrap, debug.traceback)}
_temporarySelf = nil
self.tempFunc = nil
self.tempArg = nil
return unpack(out)
end
function sandbox:restrictMetatable(meta)
local internal = Luaoop.class.data(self)
internal.restrictedMetatable[#internal.restrictedMetatable + 1] = meta
end
function sandbox:getEnv()
return Luaoop.class.data(self).env
end
function sandbox:addModuleHandler(func)
local internal = Luaoop.class.data(self)
internal.requireHandlers[#internal.requireHandlers + 1] = func
end
function sandbox:preloadModule(name, func)
local internal = Luaoop.class.data(self)
setfenv(func, internal.env)
internal.requirePreload[name] = func
end
return sandbox