This repository has been archived by the owner on Aug 30, 2019. It is now read-only.
/
sandbox_class.py
109 lines (94 loc) · 3.25 KB
/
sandbox_class.py
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
from __future__ import with_statement, absolute_import
from .config import SandboxConfig
from .proxy import proxy
def keywordsProxy(keywords):
# Dont proxy keys because function keywords must be strings
return dict(
(key, proxy(value))
for key, value in keywords.iteritems())
def _call_exec(code, globals, locals):
exec code in globals, locals
def _dictProxy(data):
items = data.items()
data.clear()
for key, value in items:
data[proxy(key)] = proxy(value)
class Sandbox(object):
PROTECTIONS = []
def __init__(self, config=None):
if config:
self.config = config
else:
self.config = SandboxConfig()
self.protections = [protection() for protection in self.PROTECTIONS]
self.execute_subprocess = None
self.call_fork = None
def _call(self, func, args, kw):
"""
Call a function in the sandbox.
"""
args = proxy(args)
kw = keywordsProxy(kw)
for protection in self.protections:
protection.enable(self)
try:
return func(*args, **kw)
finally:
for protection in reversed(self.protections):
protection.disable(self)
def call(self, func, *args, **kw):
"""
Call a function in the sandbox.
"""
if self.config.use_subprocess:
if self.call_fork is None:
from .subprocess import call_fork
self.call_fork = call_fork
return self.call_fork(self, func, args, kw)
else:
return self._call(func, args, kw)
def _execute(self, code, globals, locals):
"""
Execute the code in the sandbox:
exec code in globals, locals
"""
if globals is None:
globals = {}
for protection in self.protections:
protection.enable(self)
try:
_call_exec(code, globals, locals)
finally:
for protection in reversed(self.protections):
protection.disable(self)
def execute(self, code, globals=None, locals=None):
"""
Execute the code in the sandbox:
exec code in globals, locals
Run the code in a subprocess except if it is disabled in the sandbox
configuration.
The method has no result. By default, use globals={} to get an empty
namespace.
"""
if self.config.use_subprocess:
if self.execute_subprocess is None:
from .subprocess import execute_subprocess
self.execute_subprocess = execute_subprocess
return self.execute_subprocess(self, code, globals, locals)
else:
code = proxy(code)
if globals is not None:
_dictProxy(globals)
if locals is not None:
_dictProxy(locals)
return self._execute(code, globals, locals)
def createCallback(self, func, *args, **kw):
"""
Create a callback: the function will be called in the sandbox.
The callback takes no argument.
"""
args = proxy(args)
kw = keywordsProxy(kw)
def callback():
return self.call(func, *args, **kw)
return callback