shikashi 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +8 -0
- data/README +19 -9
- data/Rakefile +4 -3
- data/TODO +2 -0
- data/examples/basic/example6.rb +19 -0
- data/examples/basic/example7.rb +19 -0
- data/examples/redir/example1.rb +26 -0
- data/examples/redir/example2.rb +40 -0
- data/examples/timeout/example1.rb +9 -0
- data/lib/shikashi/privileges.rb +59 -8
- data/lib/shikashi/sandbox.rb +109 -63
- data/test/functional/test_timeout.rb +36 -0
- metadata +30 -8
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
0.2.0 Added control to the access to constants and global variables (See documentation)
|
2
|
+
|
3
|
+
Remove rallhook dependency, replaced by getsource
|
4
|
+
|
5
|
+
Portability and stability improved by using evalhook to hook the method calls in the place of rallhook
|
6
|
+
|
7
|
+
Added timeout restriction to the scripts executed in the sandbox (default unlimited)
|
8
|
+
|
1
9
|
0.1.2 Fixed compatibility issues with ruby1.9
|
2
10
|
|
3
11
|
0.1.1 Fixed issue 2: example2 failed when run under ruby1.9 (http://github.com/tario/shikashi/issues#issue/2)
|
data/README
CHANGED
@@ -4,19 +4,13 @@ Shikashi is an sandbox for ruby that handles all ruby method calls executed in t
|
|
4
4
|
these calls depending on the receiver object, the method name, the source file from where the call was originated
|
5
5
|
and the source file where the called method is implemented.
|
6
6
|
|
7
|
-
The permissions for each sandboxed run is fully configurable and the implementation of the methods called from
|
8
|
-
the sandbox can be replaced transparently
|
9
|
-
standard output of the script)
|
7
|
+
The permissions for each sandboxed run is fully configurable and the implementation of the methods called from within
|
8
|
+
the sandbox can be replaced transparently
|
10
9
|
|
11
|
-
The implementation of shikashi is pure ruby and
|
12
|
-
(see http://tario.github.com/rallhook/doc)
|
10
|
+
The implementation of shikashi is written in pure ruby and now implemented based in evalhook, (see http://tario.github.com/evalhook)
|
13
11
|
|
14
12
|
== Installation
|
15
13
|
|
16
|
-
=== Prerequisites
|
17
|
-
|
18
|
-
* rallhook >= 0.7.0 (found at http://github.com/tario/rallhook)
|
19
|
-
|
20
14
|
=== Gem installation
|
21
15
|
|
22
16
|
Run in the terminal:
|
@@ -203,3 +197,19 @@ Simple redirection of method, the method foo is replaced by TestWrapper::call
|
|
203
197
|
|
204
198
|
s.run(perm,"X.new.foo")
|
205
199
|
|
200
|
+
=== Timeout example
|
201
|
+
|
202
|
+
require "rubygems"
|
203
|
+
require "shikashi"
|
204
|
+
|
205
|
+
s = Shikashi::Sandbox.new
|
206
|
+
perm = Shikashi::Privileges.new
|
207
|
+
|
208
|
+
perm.allow_method :sleep
|
209
|
+
|
210
|
+
s.run(perm,"sleep 3", :timeout => 2) # raise Shikashi::Timeout::Error after 2 seconds
|
211
|
+
|
212
|
+
|
213
|
+
== Copying
|
214
|
+
|
215
|
+
Copyright (c) 2010 Dario Seminara, released under the GPL License (see LICENSE)
|
data/Rakefile
CHANGED
@@ -6,13 +6,14 @@ require 'rake/gempackagetask'
|
|
6
6
|
|
7
7
|
spec = Gem::Specification.new do |s|
|
8
8
|
s.name = 'shikashi'
|
9
|
-
s.version = '0.
|
9
|
+
s.version = '0.2.0'
|
10
10
|
s.author = 'Dario Seminara'
|
11
11
|
s.email = 'robertodarioseminara@gmail.com'
|
12
12
|
s.platform = Gem::Platform::RUBY
|
13
13
|
s.summary = 'shikashi is a ruby sandbox that permits the execution of "unprivileged" scripts by defining the permitted methods and constants the scripts can invoke (I.E., the script cannot use the File class or a RoR Model Class unless that permission is specified) "well done version" of ruby-arena-sanbox based on rallhook'
|
14
14
|
s.homepage = "http://github.com/tario/shikashi"
|
15
|
-
s.add_dependency "
|
15
|
+
s.add_dependency "evalhook", ">= 0.1.0"
|
16
|
+
s.add_dependency "getsource", ">= 0.1.0"
|
16
17
|
s.has_rdoc = true
|
17
18
|
s.extra_rdoc_files = [ 'README' ]
|
18
19
|
# s.rdoc_options << '--main' << 'README'
|
@@ -25,7 +26,7 @@ task :default => [ :test ]
|
|
25
26
|
|
26
27
|
Rake::TestTask.new('test') do |t|
|
27
28
|
t.libs << 'test'
|
28
|
-
t.pattern = '{test}
|
29
|
+
t.pattern = '{test}/**/test_*.rb'
|
29
30
|
t.verbose = true
|
30
31
|
end
|
31
32
|
|
data/TODO
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# "hello world" from within the sandbox
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "shikashi"
|
5
|
+
|
6
|
+
include Shikashi
|
7
|
+
|
8
|
+
s = Sandbox.new
|
9
|
+
priv = Privileges.new
|
10
|
+
|
11
|
+
priv.allow_method :print
|
12
|
+
priv.allow_global :$a
|
13
|
+
|
14
|
+
s.run(priv, '
|
15
|
+
$a = 9
|
16
|
+
print "assigned 9 to $a\n"
|
17
|
+
')
|
18
|
+
|
19
|
+
p $a
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# "hello world" from within the sandbox
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "shikashi"
|
5
|
+
|
6
|
+
include Shikashi
|
7
|
+
|
8
|
+
s = Sandbox.new
|
9
|
+
priv = Privileges.new
|
10
|
+
|
11
|
+
priv.allow_method :print
|
12
|
+
priv.allow_const "Object::A"
|
13
|
+
|
14
|
+
s.run(priv, '
|
15
|
+
print "assigned 8 to Object::A\n"
|
16
|
+
A = 8
|
17
|
+
')
|
18
|
+
p A
|
19
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "shikashi"
|
3
|
+
|
4
|
+
class TestWrapper < Shikashi::Sandbox::MethodWrapper
|
5
|
+
def call(*args)
|
6
|
+
print "called foo from source: #{source}, arguments: #{args.inspect} \n"
|
7
|
+
original_call(*args)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class X
|
12
|
+
def foo
|
13
|
+
print "original foo\n"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
s = Shikashi::Sandbox.new
|
18
|
+
perm = Shikashi::Privileges.new
|
19
|
+
|
20
|
+
perm.object(X).allow :new
|
21
|
+
perm.instances_of(X).allow :foo
|
22
|
+
|
23
|
+
# redirect calls to foo to TestWrapper
|
24
|
+
perm.instances_of(X).redirect :foo, TestWrapper
|
25
|
+
|
26
|
+
s.run(perm,"X.new.foo")
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "shikashi"
|
3
|
+
|
4
|
+
class TestWrapper < Shikashi::Sandbox::MethodWrapper
|
5
|
+
def call(*args)
|
6
|
+
print "called #{klass}#each block_given?:#{block_given?}, source: #{source}\n"
|
7
|
+
if block_given?
|
8
|
+
original_call(*args) do |*x|
|
9
|
+
print "yielded value #{x.first}\n"
|
10
|
+
yield(*x)
|
11
|
+
end
|
12
|
+
else
|
13
|
+
original_call(*args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
s = Shikashi::Sandbox.new
|
19
|
+
perm = Shikashi::Privileges.new
|
20
|
+
|
21
|
+
perm.instances_of(Array).allow :each
|
22
|
+
perm.instances_of(Array).redirect :each, TestWrapper
|
23
|
+
|
24
|
+
perm.instances_of(Enumerable::Enumerator).allow :each
|
25
|
+
perm.instances_of(Enumerable::Enumerator).redirect :each, TestWrapper
|
26
|
+
|
27
|
+
perm.allow_method :print
|
28
|
+
|
29
|
+
s.run perm, '
|
30
|
+
array = [1,2,3]
|
31
|
+
|
32
|
+
array.each do |x|
|
33
|
+
print x,"\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
enum = array.each
|
37
|
+
enum.each do |x|
|
38
|
+
print x,"\n"
|
39
|
+
end
|
40
|
+
'
|
data/lib/shikashi/privileges.rb
CHANGED
@@ -90,16 +90,16 @@ public
|
|
90
90
|
@redirect_hash[method_name] = method_wrapper_class
|
91
91
|
end
|
92
92
|
|
93
|
-
def handle_redirection(klass, recv, method_name,
|
93
|
+
def handle_redirection(klass, recv, method_name, sandbox)
|
94
94
|
rclass = @redirect_hash[method_name.to_sym]
|
95
95
|
|
96
96
|
if rclass
|
97
97
|
if block_given?
|
98
|
-
rclass.redirect_handler(klass, recv, method_name,
|
98
|
+
rclass.redirect_handler(klass, recv, method_name, 0, sandbox) do |mh|
|
99
99
|
yield(mh)
|
100
100
|
end
|
101
101
|
else
|
102
|
-
rclass.redirect_handler(klass, recv, method_name,
|
102
|
+
rclass.redirect_handler(klass, recv, method_name, 0, sandbox)
|
103
103
|
end
|
104
104
|
else
|
105
105
|
nil
|
@@ -114,6 +114,8 @@ public
|
|
114
114
|
@allowed_instances = Hash.new
|
115
115
|
@allowed_methods = Array.new
|
116
116
|
@allowed_klass_methods = Hash.new
|
117
|
+
@allowed_globals = Array.new
|
118
|
+
@allowed_consts = Array.new
|
117
119
|
end
|
118
120
|
|
119
121
|
private
|
@@ -189,15 +191,14 @@ public
|
|
189
191
|
@allowed_methods << method_name
|
190
192
|
end
|
191
193
|
|
192
|
-
def handle_redirection(klass, recv, method_name,
|
194
|
+
def handle_redirection(klass, recv, method_name, sandbox)
|
193
195
|
if @last_allowed
|
194
|
-
|
195
196
|
if block_given?
|
196
|
-
@last_allowed.handle_redirection(klass, recv, method_name,
|
197
|
+
@last_allowed.handle_redirection(klass, recv, method_name, sandbox) do |mh|
|
197
198
|
yield(mh)
|
198
199
|
end
|
199
200
|
else
|
200
|
-
@last_allowed.handle_redirection(klass, recv, method_name,
|
201
|
+
@last_allowed.handle_redirection(klass, recv, method_name, sandbox)
|
201
202
|
end
|
202
203
|
else
|
203
204
|
nil
|
@@ -208,7 +209,7 @@ public
|
|
208
209
|
def allow?(klass, recv, method_name, method_id)
|
209
210
|
|
210
211
|
m = nil
|
211
|
-
m = klass.
|
212
|
+
m = klass.instance_method(method_name) if method_name
|
212
213
|
|
213
214
|
begin
|
214
215
|
return true if @allowed_methods.include?(method_name)
|
@@ -284,6 +285,56 @@ public
|
|
284
285
|
end
|
285
286
|
end
|
286
287
|
|
288
|
+
|
289
|
+
def global_allowed?(varname)
|
290
|
+
@allowed_globals.include? varname
|
291
|
+
end
|
292
|
+
|
293
|
+
def const_allowed?(varname)
|
294
|
+
@allowed_consts.include? varname
|
295
|
+
end
|
296
|
+
|
297
|
+
# defines the permissions needed to create or change a global variable
|
298
|
+
#
|
299
|
+
# Example:
|
300
|
+
#
|
301
|
+
# s = Sandbox.new
|
302
|
+
# priv = Privileges.new
|
303
|
+
#
|
304
|
+
# priv.allow_method :print
|
305
|
+
# priv.allow_global :$a
|
306
|
+
#
|
307
|
+
# s.run(priv, '
|
308
|
+
# $a = 9
|
309
|
+
# print "assigned 9 to $a\n"
|
310
|
+
# ')
|
311
|
+
#
|
312
|
+
# p $a
|
313
|
+
#
|
314
|
+
def allow_global( varname )
|
315
|
+
@allowed_globals << varname
|
316
|
+
end
|
317
|
+
|
318
|
+
# defines the permissions needed to create or change a const
|
319
|
+
#
|
320
|
+
# Example:
|
321
|
+
# s = Sandbox.new
|
322
|
+
# priv = Privileges.new
|
323
|
+
#
|
324
|
+
# priv.allow_method :print
|
325
|
+
# priv.allow_const "Object::A"
|
326
|
+
#
|
327
|
+
# s.run(priv, '
|
328
|
+
# print "assigned 8 to Object::A\n"
|
329
|
+
# A = 8
|
330
|
+
# ')
|
331
|
+
#
|
332
|
+
# p A
|
333
|
+
|
334
|
+
def allow_const( varname )
|
335
|
+
@allowed_consts << varname
|
336
|
+
end
|
337
|
+
|
287
338
|
end
|
288
339
|
|
289
340
|
end
|
data/lib/shikashi/sandbox.rb
CHANGED
@@ -18,10 +18,12 @@ you should have received a copy of the gnu general public license
|
|
18
18
|
along with shikashi. if not, see <http://www.gnu.org/licenses/>.
|
19
19
|
|
20
20
|
=end
|
21
|
-
|
22
|
-
require "
|
21
|
+
require "rubygems"
|
22
|
+
require "evalhook"
|
23
23
|
require "shikashi/privileges"
|
24
24
|
require "shikashi/pick_argument"
|
25
|
+
require "getsource"
|
26
|
+
require "timeout"
|
25
27
|
|
26
28
|
module Shikashi
|
27
29
|
|
@@ -29,6 +31,14 @@ module Shikashi
|
|
29
31
|
attr_accessor :global_binding
|
30
32
|
end
|
31
33
|
|
34
|
+
module Timeout
|
35
|
+
|
36
|
+
|
37
|
+
#raised when reach the timeout in a script execution restricted by timeout (see Sandbox#run)
|
38
|
+
class Error < Exception
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
32
42
|
|
33
43
|
#The sandbox class run the sandbox, because of internal behaviour only can be use one instance
|
34
44
|
#of sandbox by thread (each different thread may have its own sandbox running in the same time)
|
@@ -119,9 +129,10 @@ module Shikashi
|
|
119
129
|
#
|
120
130
|
# class TestWrapper < Shikashi::Sandbox::MethodWrapper
|
121
131
|
# def call(*args)
|
122
|
-
# print "called each
|
132
|
+
# print "called #{klass}#each block_given?:#{block_given?}, source: #{source}\n"
|
123
133
|
# if block_given?
|
124
134
|
# original_call(*args) do |*x|
|
135
|
+
# print "yielded value #{x.first}\n"
|
125
136
|
# yield(*x)
|
126
137
|
# end
|
127
138
|
# else
|
@@ -132,8 +143,13 @@ module Shikashi
|
|
132
143
|
#
|
133
144
|
# s = Shikashi::Sandbox.new
|
134
145
|
# perm = Shikashi::Privileges.new
|
146
|
+
#
|
135
147
|
# perm.instances_of(Array).allow :each
|
148
|
+
# perm.instances_of(Array).redirect :each, TestWrapper
|
149
|
+
#
|
136
150
|
# perm.instances_of(Enumerable::Enumerator).allow :each
|
151
|
+
# perm.instances_of(Enumerable::Enumerator).redirect :each, TestWrapper
|
152
|
+
#
|
137
153
|
# perm.allow_method :print
|
138
154
|
#
|
139
155
|
# s.run perm, '
|
@@ -148,64 +164,100 @@ module Shikashi
|
|
148
164
|
# print x,"\n"
|
149
165
|
# end
|
150
166
|
# '
|
151
|
-
class MethodWrapper
|
167
|
+
class MethodWrapper
|
168
|
+
|
169
|
+
class MethodRedirect
|
170
|
+
include RedirectHelper::MethodRedirect
|
171
|
+
|
172
|
+
attr_accessor :klass
|
173
|
+
attr_accessor :method_name
|
174
|
+
attr_accessor :recv
|
175
|
+
end
|
176
|
+
|
177
|
+
attr_accessor :recv
|
178
|
+
attr_accessor :method_name
|
179
|
+
attr_accessor :klass
|
152
180
|
attr_accessor :sandbox
|
153
181
|
attr_accessor :privileges
|
154
182
|
attr_accessor :source
|
155
183
|
|
156
184
|
def self.redirect_handler(klass,recv,method_name,method_id,sandbox)
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
wrap.sandbox = sandbox
|
163
|
-
|
164
|
-
if block_given?
|
165
|
-
yield(wrap)
|
166
|
-
end
|
185
|
+
mw = self.new
|
186
|
+
mw.klass = klass
|
187
|
+
mw.recv = recv
|
188
|
+
mw.method_name = method_name
|
189
|
+
mw.sandbox = sandbox
|
167
190
|
|
168
|
-
|
169
|
-
|
170
|
-
|
191
|
+
if block_given?
|
192
|
+
yield(mw)
|
193
|
+
end
|
194
|
+
|
195
|
+
mr = MethodRedirect.new
|
196
|
+
|
197
|
+
mr.recv = mw
|
198
|
+
mr.klass = mw.class
|
199
|
+
mr.method_name = :call
|
171
200
|
|
172
|
-
|
173
|
-
class InheritedWrapper < MethodWrapper
|
174
|
-
def call(*args)
|
175
|
-
subclass = args.first
|
176
|
-
privileges.object(subclass).allow :new
|
177
|
-
privileges.instances_of(subclass).allow :initialize
|
178
|
-
original_call(*args)
|
201
|
+
mr
|
179
202
|
end
|
180
|
-
end
|
181
203
|
|
182
|
-
|
183
|
-
class DummyWrapper < MethodWrapper
|
184
|
-
def call(*args)
|
204
|
+
def original_call(*args)
|
185
205
|
if block_given?
|
186
|
-
|
206
|
+
klass.instance_method(method_name).bind(recv).call(*args) do |*x|
|
187
207
|
yield(*x)
|
188
208
|
end
|
189
209
|
else
|
190
|
-
|
210
|
+
klass.instance_method(method_name).bind(recv).call(*args)
|
191
211
|
end
|
192
212
|
end
|
193
213
|
end
|
194
214
|
|
195
|
-
class
|
215
|
+
class EvalhookHandler < EvalHook::HookHandler
|
196
216
|
attr_accessor :sandbox
|
197
217
|
attr_accessor :redirect
|
198
218
|
|
199
|
-
def
|
219
|
+
def handle_gasgn( global_id, value )
|
220
|
+
source = caller[1].split(":").first
|
221
|
+
|
222
|
+
privileges = sandbox.privileges[source]
|
223
|
+
if privileges
|
224
|
+
unless privileges.global_allowed? global_id
|
225
|
+
raise SecurityError.new("Cannot assign global variable #{global_id}")
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
nil
|
230
|
+
end
|
231
|
+
|
232
|
+
def handle_cdecl(klass, const_id, value)
|
233
|
+
source = caller[1].split(":").first
|
234
|
+
|
235
|
+
privileges = sandbox.privileges[source]
|
236
|
+
if privileges
|
237
|
+
unless privileges.const_allowed? "#{klass}::#{const_id}"
|
238
|
+
raise SecurityError.new("Cannot assign const #{klass}::#{const_id}")
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
nil
|
243
|
+
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
def handle_method(klass, recv, method_name)
|
200
248
|
source = nil
|
249
|
+
|
250
|
+
method_id = 0
|
251
|
+
|
201
252
|
if method_name
|
202
253
|
|
203
|
-
source = caller.
|
204
|
-
dest_source = klass.
|
254
|
+
source = caller[1].split(":").first
|
255
|
+
dest_source = klass.instance_method(method_name).body.file
|
205
256
|
|
206
257
|
privileges = nil
|
207
258
|
if source != dest_source then
|
208
259
|
privileges = sandbox.privileges[source]
|
260
|
+
|
209
261
|
if privileges then
|
210
262
|
privileges = privileges.dup
|
211
263
|
loop_source = source
|
@@ -229,12 +281,6 @@ module Shikashi
|
|
229
281
|
end
|
230
282
|
end
|
231
283
|
|
232
|
-
if method_name == :inherited and recv.instance_of? Class
|
233
|
-
mw = InheritedWrapper.redirect_handler(klass,recv,method_name,method_id,sandbox)
|
234
|
-
mw.recv.privileges = privileges
|
235
|
-
return mw
|
236
|
-
end
|
237
|
-
|
238
284
|
return nil if method_name == :instance_eval
|
239
285
|
return nil if method_name == :binding
|
240
286
|
|
@@ -245,20 +291,13 @@ module Shikashi
|
|
245
291
|
end
|
246
292
|
end
|
247
293
|
|
248
|
-
if dest_source == ""
|
249
|
-
return nil if (method_name.to_s == "core#define_method")
|
250
|
-
return nil if (method_name.to_s == "core#define_singleton_method")
|
251
|
-
return DummyWrapper.redirect_handler(klass,recv,method_name,method_id,sandbox)
|
252
|
-
end
|
253
|
-
|
254
294
|
end
|
255
295
|
|
256
|
-
|
257
296
|
if privileges
|
258
|
-
privileges.handle_redirection(klass,recv,method_name,
|
259
|
-
|
260
|
-
|
261
|
-
|
297
|
+
privileges.handle_redirection(klass,recv,method_name,sandbox) do |mh|
|
298
|
+
mh.privileges = privileges
|
299
|
+
mh.source = source
|
300
|
+
end
|
262
301
|
end
|
263
302
|
|
264
303
|
end # if
|
@@ -280,6 +319,8 @@ module Shikashi
|
|
280
319
|
# The default is a binding in the global context
|
281
320
|
# :source Optional argument to indicate the "source name", (visible in the backtraces). Only can
|
282
321
|
# be specified as hash parameter
|
322
|
+
# :timeout Optional argument to restrict the execution time of the script to a given value in seconds
|
323
|
+
# (accepts integer and decimal values), when timeout hits Shikashi::Timeout::Error is raised
|
283
324
|
#
|
284
325
|
#
|
285
326
|
#The arguments can be passed in any order and using hash notation or not, examples:
|
@@ -331,25 +372,30 @@ module Shikashi
|
|
331
372
|
|
332
373
|
def run(*args)
|
333
374
|
|
334
|
-
handler =
|
375
|
+
handler = EvalhookHandler.new
|
335
376
|
handler.redirect = @redirect_hash
|
336
377
|
handler.sandbox = self
|
337
378
|
|
379
|
+
t = args.pick(:timeout) do nil end
|
380
|
+
raise Shikashi::Timeout::Error if t == 0
|
381
|
+
t = t || 0
|
382
|
+
|
338
383
|
if block_given?
|
339
|
-
|
340
|
-
yield
|
341
|
-
end
|
384
|
+
yield
|
342
385
|
else
|
386
|
+
begin
|
387
|
+
timeout t do
|
388
|
+
privileges_ = args.pick(Privileges,:privileges) do Privileges.new end
|
389
|
+
code = args.pick(String,:code)
|
390
|
+
binding_ = args.pick(Binding,:binding) do Shikashi.global_binding end
|
391
|
+
source = args.pick(:source) do generate_id end
|
343
392
|
|
344
|
-
|
345
|
-
code = args.pick(String,:code)
|
346
|
-
binding_ = args.pick(Binding,:binding) do Shikashi.global_binding end
|
347
|
-
source = args.pick(:source) do generate_id end
|
348
|
-
|
349
|
-
self.privileges[source] = privileges_
|
393
|
+
self.privileges[source] = privileges_
|
350
394
|
|
351
|
-
|
352
|
-
|
395
|
+
handler.evalhook(code, binding_, source)
|
396
|
+
end
|
397
|
+
rescue ::Timeout::Error
|
398
|
+
raise Shikashi::Timeout::Error
|
353
399
|
end
|
354
400
|
end
|
355
401
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "shikashi"
|
3
|
+
|
4
|
+
class TimeoutTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def _test_timeout(execution_delay, timeout)
|
7
|
+
priv = Shikashi::Privileges.new
|
8
|
+
# allow the execution of the method sleep to emulate an execution delay
|
9
|
+
priv.allow_method :sleep
|
10
|
+
|
11
|
+
if execution_delay > timeout
|
12
|
+
assert_raise Shikashi::Timeout::Error do
|
13
|
+
# specify the timeout and the current binding to use the execution_delay parameter
|
14
|
+
Shikashi::Sandbox.new.run("sleep execution_delay", priv, binding, :timeout => timeout)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
assert_nothing_raised do
|
18
|
+
Shikashi::Sandbox.new.run("sleep execution_delay", priv, binding, :timeout => timeout)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.add_test(name, execution_delay, timeout)
|
24
|
+
define_method("test_"+name) do
|
25
|
+
_test_timeout(execution_delay, timeout)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
add_test "basic",2,1
|
30
|
+
add_test "float",0.2,0.1
|
31
|
+
add_test "float_no_hit",0.1,0.2
|
32
|
+
add_test "zero", 1,0
|
33
|
+
add_test "zero_no_hit", 0,1
|
34
|
+
|
35
|
+
end
|
36
|
+
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shikashi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
- 1
|
9
8
|
- 2
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dario Seminara
|
@@ -15,25 +15,41 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-10-30 00:00:00 -03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
22
|
+
name: evalhook
|
23
23
|
prerelease: false
|
24
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 27
|
30
30
|
segments:
|
31
31
|
- 0
|
32
|
-
-
|
32
|
+
- 1
|
33
33
|
- 0
|
34
|
-
version: 0.
|
34
|
+
version: 0.1.0
|
35
35
|
type: :runtime
|
36
36
|
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: getsource
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 27
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 1
|
49
|
+
- 0
|
50
|
+
version: 0.1.0
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
37
53
|
description:
|
38
54
|
email: robertodarioseminara@gmail.com
|
39
55
|
executables: []
|
@@ -47,8 +63,13 @@ files:
|
|
47
63
|
- examples/basic/example3.rb
|
48
64
|
- examples/basic/example5.rb
|
49
65
|
- examples/basic/example4.rb
|
66
|
+
- examples/basic/example6.rb
|
50
67
|
- examples/basic/example.rb
|
68
|
+
- examples/basic/example7.rb
|
51
69
|
- examples/basic/example2.rb
|
70
|
+
- examples/timeout/example1.rb
|
71
|
+
- examples/redir/example1.rb
|
72
|
+
- examples/redir/example2.rb
|
52
73
|
- lib/shikashi.rb
|
53
74
|
- lib/shikashi/pick_argument.rb
|
54
75
|
- lib/shikashi/sandbox.rb
|
@@ -56,6 +77,7 @@ files:
|
|
56
77
|
- lib/shikashi/privileges/singleton_methods.rb
|
57
78
|
- lib/shikashi/privileges/classes.rb
|
58
79
|
- lib/shikashi/privileges.rb
|
80
|
+
- test/functional/test_timeout.rb
|
59
81
|
- AUTHORS
|
60
82
|
- CHANGELOG
|
61
83
|
- README
|