jruby_sandbox 0.2.2-java → 0.2.3-java
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +5 -0
- data/README.md +37 -26
- data/ext/java/sandbox/BoxedClass.java +10 -0
- data/ext/java/sandbox/SandboxFull.java +16 -11
- data/ext/java/sandbox/SandboxModule.java +23 -0
- data/ext/java/sandbox/SandboxService.java +1 -17
- data/jruby_sandbox.gemspec +18 -17
- data/lib/sandbox.rb +4 -397
- data/lib/sandbox/safe.rb +399 -0
- data/lib/sandbox/version.rb +1 -1
- data/spec/exploits_spec.rb +56 -49
- data/spec/sandbox_spec.rb +75 -75
- metadata +6 -4
- data/.rvmrc +0 -47
- data/Gemfile.lock +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20db9f92162ab81d708ba65399e609c732fd1112
|
4
|
+
data.tar.gz: 3e23f62108ab2637d034f1c90f04da46e1569da7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed461f57a6f7b2fd11f2eee081356d05a1a2f81a4df582ebe13b9efa393812bf457ce5d861bca90c1dd4aaee0b193810b7e724727beafdb4797b34d5bd326685
|
7
|
+
data.tar.gz: 7002942c8eed69c5ede100b792f663431b922fc7eb013fcabfd6a899ba9726ab62b5ddbc2a64a170e398a0ee55b04f2157f98d2ddc4bd727c696e5c8b1cf2236
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,17 +1,24 @@
|
|
1
1
|
JRuby Sandbox
|
2
2
|
=============
|
3
3
|
|
4
|
-
|
4
|
+
[](https://travis-ci.org/omghax/jruby-sandbox)
|
5
|
+
|
6
|
+
The JRuby sandbox is a reimplementation of \_why's freaky freaky sandbox
|
5
7
|
in JRuby, and is heavily based on [javasand][1] by Ola Bini, but updated
|
6
|
-
for JRuby 1.
|
8
|
+
for JRuby 1.7.
|
7
9
|
|
8
10
|
## Prerequisites
|
9
11
|
|
10
|
-
This gem
|
11
|
-
|
12
|
-
|
12
|
+
This gem was developed against JRuby 1.7.6, and is known to work with 1.7.8,
|
13
|
+
but has not been tested against other versions, so proceed at your own risk.
|
14
|
+
The Travis CI configuration specifies the `jruby-19mode` target, which floats
|
15
|
+
between exact versions of JRuby. At the time of writing, this is currently
|
16
|
+
JRuby 1.7.8. You can see a list of Travis CI's provided rubies [here][2]. As
|
17
|
+
long as the build is green you should be good to go.
|
18
|
+
|
19
|
+
Installing JRuby is simple with RVM:
|
13
20
|
|
14
|
-
rvm install jruby-1.6
|
21
|
+
rvm install jruby-1.7.6
|
15
22
|
|
16
23
|
## Building
|
17
24
|
|
@@ -27,50 +34,53 @@ code without polluting the host environment.
|
|
27
34
|
=> true
|
28
35
|
>> sand = Sandbox::Full.new
|
29
36
|
=> #<Sandbox::Full:0x46377e2a>
|
30
|
-
>> sand.eval("x = 1 + 2")
|
37
|
+
>> sand.eval("x = 1 + 2") # we've defined x in the sandbox
|
31
38
|
=> 3
|
32
39
|
>> sand.eval("x")
|
33
40
|
=> 3
|
34
|
-
>> x
|
41
|
+
>> x # but it hasn't leaked out into the host interpreter
|
35
42
|
NameError: undefined local variable or method `x' for #<Object:0x11cdc190>
|
36
43
|
|
37
|
-
There's also `Sandbox::Full#require`, which lets you invoke
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
yet).
|
44
|
+
There's also `Sandbox::Full#require`, which lets you invoke `Kernel#require`
|
45
|
+
directly for the sandbox, so you can load any trusted core libraries. Note that
|
46
|
+
this is a direct binding to `Kernel#require`, so it will only load ruby stdlib
|
47
|
+
libraries (i.e. no rubygems support yet).
|
42
48
|
|
43
49
|
## Sandbox::Safe usage
|
44
50
|
|
45
|
-
Sandbox::Safe exposes an `#activate!` method which will lock down the sandbox,
|
51
|
+
Sandbox::Safe exposes an `#activate!` method which will lock down the sandbox,
|
52
|
+
removing unsafe methods. Before calling `#activate!`, Sandbox::Safe is the same
|
53
|
+
as Sandbox::Full.
|
46
54
|
|
47
55
|
>> require 'sandbox'
|
48
|
-
=> true
|
56
|
+
=> true
|
49
57
|
>> sand = Sandbox.safe
|
50
|
-
=> #<Sandbox::Safe:0x17072b90>
|
58
|
+
=> #<Sandbox::Safe:0x17072b90>
|
51
59
|
>> sand.eval %{`echo HELLO`}
|
52
|
-
=> "HELLO\n"
|
53
|
-
>> sand.activate!
|
60
|
+
=> "HELLO\n"
|
61
|
+
>> sand.activate!
|
54
62
|
>> sand.eval %{`echo HELLO`}
|
55
63
|
Sandbox::SandboxException: NoMethodError: undefined method ``' for main:Object
|
56
64
|
|
57
|
-
Sandbox::Safe works by whitelisting methods to keep, and removing the rest.
|
65
|
+
Sandbox::Safe works by whitelisting methods to keep, and removing the rest.
|
66
|
+
Checkout sandbox.rb for which methods are kept.
|
58
67
|
|
59
|
-
Sandbox::Safe.activate! will also isolate the sandbox environment from the
|
68
|
+
Sandbox::Safe.activate! will also isolate the sandbox environment from the
|
69
|
+
filesystem using FakeFS.
|
60
70
|
|
61
71
|
>> require 'sandbox'
|
62
|
-
=> true
|
72
|
+
=> true
|
63
73
|
>> s = Sandbox.safe
|
64
|
-
=> #<Sandbox::Safe:0x3fdb8a73>
|
74
|
+
=> #<Sandbox::Safe:0x3fdb8a73>
|
65
75
|
>> s.eval('Dir["/"]')
|
66
|
-
=> ["/"]
|
76
|
+
=> ["/"]
|
67
77
|
>> s.eval('Dir["/*"]')
|
68
|
-
=> ["/Applications", "/bin", "/cores", "/dev", etc.]
|
78
|
+
=> ["/Applications", "/bin", "/cores", "/dev", etc.]
|
69
79
|
> s.activate!
|
70
80
|
>> s.eval('Dir["/*"]')
|
71
|
-
=> []
|
81
|
+
=> []
|
72
82
|
> Dir['/*']
|
73
|
-
=> ["/Applications", "/bin", "/cores", "/dev", etc.]
|
83
|
+
=> ["/Applications", "/bin", "/cores", "/dev", etc.]
|
74
84
|
|
75
85
|
## Known Issues / TODOs
|
76
86
|
|
@@ -78,3 +88,4 @@ Sandbox::Safe.activate! will also isolate the sandbox environment from the files
|
|
78
88
|
sandbox to loop indefinitely and block the host interpreter.
|
79
89
|
|
80
90
|
[1]: http://ola-bini.blogspot.com/2006/12/freaky-freaky-sandbox-has-come-to-jruby.html
|
91
|
+
[2]: http://about.travis-ci.org/docs/user/ci-environment/#Ruby-(aka-common)-VM-images
|
@@ -1,5 +1,7 @@
|
|
1
1
|
package sandbox;
|
2
2
|
|
3
|
+
import org.jruby.Ruby;
|
4
|
+
import org.jruby.RubyClass;
|
3
5
|
import org.jruby.anno.JRubyClass;
|
4
6
|
import org.jruby.anno.JRubyMethod;
|
5
7
|
import org.jruby.runtime.builtin.IRubyObject;
|
@@ -7,6 +9,14 @@ import org.jruby.runtime.Block;
|
|
7
9
|
|
8
10
|
@JRubyClass(name="BoxedClass")
|
9
11
|
public class BoxedClass {
|
12
|
+
protected static RubyClass createBoxedClassClass(final Ruby runtime) {
|
13
|
+
RubyClass cObject = runtime.getObject();
|
14
|
+
RubyClass cBoxedClass = runtime.defineClass("BoxedClass", cObject, cObject.getAllocator());
|
15
|
+
cBoxedClass.defineAnnotatedMethods(BoxedClass.class);
|
16
|
+
|
17
|
+
return cBoxedClass;
|
18
|
+
}
|
19
|
+
|
10
20
|
@JRubyMethod(module=true, rest=true)
|
11
21
|
public static IRubyObject method_missing(IRubyObject recv, IRubyObject[] args, Block block) {
|
12
22
|
IRubyObject[] args2 = new IRubyObject[args.length - 1];
|
@@ -14,6 +14,7 @@ import org.jruby.anno.JRubyClass;
|
|
14
14
|
import org.jruby.anno.JRubyMethod;
|
15
15
|
import org.jruby.internal.runtime.methods.DynamicMethod;
|
16
16
|
import org.jruby.runtime.Block;
|
17
|
+
import org.jruby.runtime.ObjectAllocator;
|
17
18
|
import org.jruby.runtime.builtin.IRubyObject;
|
18
19
|
import org.jruby.common.IRubyWarnings;
|
19
20
|
import org.jruby.exceptions.RaiseException;
|
@@ -22,10 +23,16 @@ import org.jruby.runtime.DynamicScope;
|
|
22
23
|
|
23
24
|
@JRubyClass(name="Sandbox::Full")
|
24
25
|
public class SandboxFull extends RubyObject {
|
26
|
+
protected static ObjectAllocator FULL_ALLOCATOR = new ObjectAllocator() {
|
27
|
+
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
28
|
+
return new SandboxFull(runtime, klass);
|
29
|
+
}
|
30
|
+
};
|
31
|
+
|
25
32
|
private Ruby wrapped;
|
26
33
|
private DynamicScope currentScope;
|
27
34
|
|
28
|
-
|
35
|
+
protected SandboxFull(Ruby runtime, RubyClass type) {
|
29
36
|
super(runtime, type);
|
30
37
|
reload();
|
31
38
|
}
|
@@ -44,12 +51,10 @@ public class SandboxFull extends RubyObject {
|
|
44
51
|
cfg.setProfile(profile);
|
45
52
|
|
46
53
|
wrapped = Ruby.newInstance(cfg);
|
47
|
-
|
48
|
-
RubyClass cBoxedClass = wrapped.defineClass("BoxedClass", wrapped.getObject(), wrapped.getObject().getAllocator());
|
49
|
-
cBoxedClass.defineAnnotatedMethods(BoxedClass.class);
|
50
|
-
|
51
54
|
currentScope = wrapped.getCurrentContext().getCurrentScope();
|
52
55
|
|
56
|
+
BoxedClass.createBoxedClassClass(wrapped);
|
57
|
+
|
53
58
|
return this;
|
54
59
|
}
|
55
60
|
|
@@ -115,14 +120,14 @@ public class SandboxFull extends RubyObject {
|
|
115
120
|
RubyClass klass = (RubyClass) sup;
|
116
121
|
if (wrappedModule == wrapped.getObject()) {
|
117
122
|
|
118
|
-
if (link || runtimeModule instanceof RubyClass){ // if this is a ref and not an import
|
123
|
+
if (link || runtimeModule instanceof RubyClass) { // if this is a ref and not an import
|
119
124
|
wrappedModule = wrapped.defineClass(name, klass, klass.getAllocator());
|
120
125
|
} else {
|
121
126
|
wrappedModule = wrapped.defineModule(name);
|
122
127
|
}
|
123
128
|
|
124
129
|
} else {
|
125
|
-
if (runtimeModule instanceof RubyClass){
|
130
|
+
if (runtimeModule instanceof RubyClass) {
|
126
131
|
wrappedModule = wrappedModule.defineClassUnder(name, klass, klass.getAllocator());
|
127
132
|
} else {
|
128
133
|
wrappedModule = wrappedModule.defineModuleUnder(name);
|
@@ -273,16 +278,16 @@ public class SandboxFull extends RubyObject {
|
|
273
278
|
|
274
279
|
protected static IRubyObject getLinkedObject(IRubyObject arg) {
|
275
280
|
IRubyObject object = arg.getRuntime().getNil();
|
276
|
-
if (arg.getInstanceVariables().
|
277
|
-
object = (IRubyObject) arg.getInstanceVariables().
|
281
|
+
if (arg.getInstanceVariables().hasInstanceVariable("__link__")) {
|
282
|
+
object = (IRubyObject) arg.getInstanceVariables().getInstanceVariable("__link__");
|
278
283
|
}
|
279
284
|
return object;
|
280
285
|
}
|
281
286
|
|
282
287
|
protected static IRubyObject getLinkedBox(IRubyObject arg) {
|
283
288
|
IRubyObject object = arg.getRuntime().getNil();
|
284
|
-
if (arg.getInstanceVariables().
|
285
|
-
object = (IRubyObject) arg.getInstanceVariables().
|
289
|
+
if (arg.getInstanceVariables().hasInstanceVariable("__box__")) {
|
290
|
+
object = (IRubyObject) arg.getInstanceVariables().getInstanceVariable("__box__");
|
286
291
|
}
|
287
292
|
return object;
|
288
293
|
}
|
@@ -1,10 +1,33 @@
|
|
1
1
|
package sandbox;
|
2
2
|
|
3
3
|
import org.jruby.Profile;
|
4
|
+
import org.jruby.Ruby;
|
5
|
+
import org.jruby.RubyClass;
|
6
|
+
import org.jruby.RubyModule;
|
7
|
+
import org.jruby.anno.JRubyClass;
|
4
8
|
import org.jruby.anno.JRubyMethod;
|
5
9
|
import org.jruby.runtime.builtin.IRubyObject;
|
6
10
|
|
7
11
|
public class SandboxModule {
|
12
|
+
/**
|
13
|
+
* Create the Sandbox module and add it to the Ruby runtime.
|
14
|
+
*/
|
15
|
+
public static RubyModule createSandboxModule(final Ruby runtime) {
|
16
|
+
RubyModule mSandbox = runtime.defineModule("Sandbox");
|
17
|
+
mSandbox.defineAnnotatedMethods(SandboxModule.class);
|
18
|
+
|
19
|
+
RubyClass cObject = runtime.getObject();
|
20
|
+
RubyClass cSandboxFull = mSandbox.defineClassUnder("Full", cObject, SandboxFull.FULL_ALLOCATOR);
|
21
|
+
cSandboxFull.defineAnnotatedMethods(SandboxFull.class);
|
22
|
+
RubyClass cStandardError = runtime.getStandardError();
|
23
|
+
RubyClass cSandboxException = mSandbox.defineClassUnder("SandboxException", cStandardError, cStandardError.getAllocator());
|
24
|
+
|
25
|
+
return mSandbox;
|
26
|
+
}
|
27
|
+
|
28
|
+
@JRubyClass(name="Sandbox::SandboxException", parent="StandardError")
|
29
|
+
public static class SandboxException {}
|
30
|
+
|
8
31
|
@JRubyMethod(name="current", meta=true)
|
9
32
|
public static IRubyObject s_current(IRubyObject recv) {
|
10
33
|
Profile prof = recv.getRuntime().getProfile();
|
@@ -3,10 +3,6 @@ package sandbox;
|
|
3
3
|
import java.io.IOException;
|
4
4
|
|
5
5
|
import org.jruby.Ruby;
|
6
|
-
import org.jruby.RubyClass;
|
7
|
-
import org.jruby.RubyModule;
|
8
|
-
import org.jruby.runtime.ObjectAllocator;
|
9
|
-
import org.jruby.runtime.builtin.IRubyObject;
|
10
6
|
import org.jruby.runtime.load.BasicLibraryService;
|
11
7
|
|
12
8
|
public class SandboxService implements BasicLibraryService {
|
@@ -16,18 +12,6 @@ public class SandboxService implements BasicLibraryService {
|
|
16
12
|
}
|
17
13
|
|
18
14
|
private void init(Ruby runtime) {
|
19
|
-
|
20
|
-
mSandbox.defineAnnotatedMethods(SandboxModule.class);
|
21
|
-
|
22
|
-
RubyClass cSandboxFull = mSandbox.defineClassUnder("Full", runtime.getObject(), FULL_ALLOCATOR);
|
23
|
-
cSandboxFull.defineAnnotatedMethods(SandboxFull.class);
|
24
|
-
|
25
|
-
RubyClass cSandboxException = mSandbox.defineClassUnder("SandboxException", runtime.getException(), runtime.getException().getAllocator());
|
15
|
+
SandboxModule.createSandboxModule(runtime);
|
26
16
|
}
|
27
|
-
|
28
|
-
protected static final ObjectAllocator FULL_ALLOCATOR = new ObjectAllocator() {
|
29
|
-
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
30
|
-
return new SandboxFull(runtime, klass);
|
31
|
-
}
|
32
|
-
};
|
33
17
|
}
|
data/jruby_sandbox.gemspec
CHANGED
@@ -1,27 +1,28 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path(
|
3
|
-
require
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "sandbox/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
6
|
+
s.name = "jruby_sandbox"
|
7
7
|
s.version = Sandbox::VERSION
|
8
|
-
s.platform =
|
9
|
-
s.authors = [
|
10
|
-
s.email = [
|
11
|
-
s.homepage =
|
12
|
-
s.summary =
|
8
|
+
s.platform = "java"
|
9
|
+
s.authors = ["Dray Lacy", "Eric Allam"]
|
10
|
+
s.email = ["dray@envylabs.com", "eric@envylabs.com"]
|
11
|
+
s.homepage = "http://github.com/omghax/jruby-sandbox"
|
12
|
+
s.summary = "Sandbox support for JRuby"
|
13
13
|
s.description = "A version of _why's Freaky Freaky Sandbox for JRuby."
|
14
14
|
|
15
|
-
s.rubyforge_project =
|
15
|
+
s.rubyforge_project = "jruby_sandbox"
|
16
16
|
|
17
|
-
s.files = `git ls-files`.split("\n") + [
|
17
|
+
s.files = `git ls-files`.split("\n") + ["lib/sandbox/sandbox.jar"]
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
-
s.require_paths = [
|
21
|
-
|
22
|
-
s.add_dependency
|
23
|
-
|
24
|
-
s.add_development_dependency
|
25
|
-
s.add_development_dependency
|
26
|
-
s.add_development_dependency
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_dependency "fakefs"
|
23
|
+
|
24
|
+
s.add_development_dependency "rake"
|
25
|
+
s.add_development_dependency "rake-compiler"
|
26
|
+
s.add_development_dependency "rspec"
|
27
|
+
s.add_development_dependency "yard"
|
27
28
|
end
|
data/lib/sandbox.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "sandbox/sandbox"
|
2
|
+
require "sandbox/version"
|
3
|
+
require "sandbox/safe"
|
4
4
|
|
5
5
|
module Sandbox
|
6
|
-
PRELUDE = File.expand_path(
|
7
|
-
|
8
|
-
TimeoutError = Class.new(Exception)
|
6
|
+
PRELUDE = File.expand_path("../sandbox/prelude.rb", __FILE__).freeze # :nodoc:
|
9
7
|
|
10
8
|
class << self
|
11
9
|
def new
|
@@ -16,395 +14,4 @@ module Sandbox
|
|
16
14
|
Safe.new
|
17
15
|
end
|
18
16
|
end
|
19
|
-
|
20
|
-
class Safe < Full
|
21
|
-
def activate!
|
22
|
-
activate_fakefs
|
23
|
-
|
24
|
-
keep_singleton_methods(:Kernel, KERNEL_S_METHODS)
|
25
|
-
keep_singleton_methods(:Symbol, SYMBOL_S_METHODS)
|
26
|
-
keep_singleton_methods(:String, STRING_S_METHODS)
|
27
|
-
keep_singleton_methods(:IO, IO_S_METHODS)
|
28
|
-
|
29
|
-
keep_methods(:Kernel, KERNEL_METHODS)
|
30
|
-
keep_methods(:NilClass, NILCLASS_METHODS)
|
31
|
-
keep_methods(:Symbol, SYMBOL_METHODS)
|
32
|
-
keep_methods(:TrueClass, TRUECLASS_METHODS)
|
33
|
-
keep_methods(:FalseClass, FALSECLASS_METHODS)
|
34
|
-
keep_methods(:Enumerable, ENUMERABLE_METHODS)
|
35
|
-
keep_methods(:String, STRING_METHODS)
|
36
|
-
|
37
|
-
Kernel.class_eval do
|
38
|
-
def `(*args)
|
39
|
-
raise NoMethodError, "` is unavailable"
|
40
|
-
end
|
41
|
-
def system(*args)
|
42
|
-
raise NoMethodError, "system is unavailable"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def activate_fakefs
|
48
|
-
require 'fileutils'
|
49
|
-
|
50
|
-
# unfortunately, the authors of FakeFS used `extend self` in FileUtils, instead of `module_function`.
|
51
|
-
# I fixed it for them
|
52
|
-
(FakeFS::FileUtils.methods - Module.methods - Kernel.methods).each do |module_method_name|
|
53
|
-
FakeFS::FileUtils.send(:module_function, module_method_name)
|
54
|
-
end
|
55
|
-
|
56
|
-
import FakeFS
|
57
|
-
ref FakeFS::Dir
|
58
|
-
ref FakeFS::File
|
59
|
-
ref FakeFS::FileTest
|
60
|
-
import FakeFS::FileUtils #import FileUtils because it is a module
|
61
|
-
|
62
|
-
# this is basically what FakeFS.activate! does, but we want to do it in the sandbox
|
63
|
-
# so we have to live with this:
|
64
|
-
eval <<-RUBY
|
65
|
-
Object.class_eval do
|
66
|
-
remove_const(:Dir)
|
67
|
-
remove_const(:File)
|
68
|
-
remove_const(:FileTest)
|
69
|
-
remove_const(:FileUtils)
|
70
|
-
|
71
|
-
const_set(:Dir, FakeFS::Dir)
|
72
|
-
const_set(:File, FakeFS::File)
|
73
|
-
const_set(:FileUtils, FakeFS::FileUtils)
|
74
|
-
const_set(:FileTest, FakeFS::FileTest)
|
75
|
-
end
|
76
|
-
|
77
|
-
[Dir, File, FileUtils, FileTest].each do |fake_class|
|
78
|
-
fake_class.class_eval do
|
79
|
-
def self.class_eval
|
80
|
-
raise NoMethodError, "class_eval is unavailable"
|
81
|
-
end
|
82
|
-
def self.instance_eval
|
83
|
-
raise NoMethodError, "instance_eval is unavailable"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
RUBY
|
88
|
-
|
89
|
-
FakeFS::FileSystem.clear
|
90
|
-
end
|
91
|
-
|
92
|
-
def eval(code, options={})
|
93
|
-
|
94
|
-
if seconds = options[:timeout]
|
95
|
-
sandbox_timeout(code, seconds) do
|
96
|
-
super code
|
97
|
-
end
|
98
|
-
else
|
99
|
-
super code
|
100
|
-
end
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
private
|
105
|
-
|
106
|
-
def sandbox_timeout(name, seconds)
|
107
|
-
val, exc = nil
|
108
|
-
|
109
|
-
thread = Thread.start(name) do
|
110
|
-
begin
|
111
|
-
val = yield
|
112
|
-
rescue Exception => exc
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
thread.join(seconds)
|
117
|
-
|
118
|
-
if thread.alive?
|
119
|
-
if thread.respond_to? :kill!
|
120
|
-
thread.kill!
|
121
|
-
else
|
122
|
-
thread.kill
|
123
|
-
end
|
124
|
-
|
125
|
-
timed_out = true
|
126
|
-
end
|
127
|
-
|
128
|
-
if timed_out
|
129
|
-
raise TimeoutError, "#{self.class} timed out"
|
130
|
-
elsif exc
|
131
|
-
raise exc
|
132
|
-
else
|
133
|
-
val
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
IO_S_METHODS = %w[
|
138
|
-
new
|
139
|
-
foreach
|
140
|
-
open
|
141
|
-
]
|
142
|
-
|
143
|
-
KERNEL_S_METHODS = %w[
|
144
|
-
Array
|
145
|
-
binding
|
146
|
-
block_given?
|
147
|
-
catch
|
148
|
-
chomp
|
149
|
-
chomp!
|
150
|
-
chop
|
151
|
-
chop!
|
152
|
-
eval
|
153
|
-
fail
|
154
|
-
Float
|
155
|
-
format
|
156
|
-
global_variables
|
157
|
-
gsub
|
158
|
-
gsub!
|
159
|
-
Integer
|
160
|
-
iterator?
|
161
|
-
lambda
|
162
|
-
local_variables
|
163
|
-
loop
|
164
|
-
method_missing
|
165
|
-
proc
|
166
|
-
raise
|
167
|
-
scan
|
168
|
-
split
|
169
|
-
sprintf
|
170
|
-
String
|
171
|
-
sub
|
172
|
-
sub!
|
173
|
-
throw
|
174
|
-
].freeze
|
175
|
-
|
176
|
-
SYMBOL_S_METHODS = %w[
|
177
|
-
all_symbols
|
178
|
-
].freeze
|
179
|
-
|
180
|
-
STRING_S_METHODS = %w[
|
181
|
-
new
|
182
|
-
].freeze
|
183
|
-
|
184
|
-
KERNEL_METHODS = %w[
|
185
|
-
==
|
186
|
-
===
|
187
|
-
=~
|
188
|
-
Array
|
189
|
-
binding
|
190
|
-
block_given?
|
191
|
-
catch
|
192
|
-
chomp
|
193
|
-
chomp!
|
194
|
-
chop
|
195
|
-
chop!
|
196
|
-
class
|
197
|
-
clone
|
198
|
-
dup
|
199
|
-
eql?
|
200
|
-
equal?
|
201
|
-
eval
|
202
|
-
fail
|
203
|
-
Float
|
204
|
-
format
|
205
|
-
freeze
|
206
|
-
frozen?
|
207
|
-
global_variables
|
208
|
-
gsub
|
209
|
-
gsub!
|
210
|
-
hash
|
211
|
-
id
|
212
|
-
initialize_copy
|
213
|
-
inspect
|
214
|
-
instance_eval
|
215
|
-
instance_of?
|
216
|
-
instance_variables
|
217
|
-
instance_variable_get
|
218
|
-
instance_variable_set
|
219
|
-
instance_variable_defined?
|
220
|
-
Integer
|
221
|
-
is_a?
|
222
|
-
iterator?
|
223
|
-
kind_of?
|
224
|
-
lambda
|
225
|
-
local_variables
|
226
|
-
loop
|
227
|
-
methods
|
228
|
-
method_missing
|
229
|
-
nil?
|
230
|
-
private_methods
|
231
|
-
print
|
232
|
-
proc
|
233
|
-
protected_methods
|
234
|
-
public_methods
|
235
|
-
raise
|
236
|
-
remove_instance_variable
|
237
|
-
respond_to?
|
238
|
-
respond_to_missing?
|
239
|
-
scan
|
240
|
-
send
|
241
|
-
singleton_methods
|
242
|
-
singleton_method_added
|
243
|
-
singleton_method_removed
|
244
|
-
singleton_method_undefined
|
245
|
-
split
|
246
|
-
sprintf
|
247
|
-
String
|
248
|
-
sub
|
249
|
-
sub!
|
250
|
-
taint
|
251
|
-
tainted?
|
252
|
-
throw
|
253
|
-
to_a
|
254
|
-
to_s
|
255
|
-
type
|
256
|
-
untaint
|
257
|
-
__send__
|
258
|
-
].freeze
|
259
|
-
|
260
|
-
NILCLASS_METHODS = %w[
|
261
|
-
&
|
262
|
-
inspect
|
263
|
-
nil?
|
264
|
-
to_a
|
265
|
-
to_f
|
266
|
-
to_i
|
267
|
-
to_s
|
268
|
-
^
|
269
|
-
|
|
270
|
-
].freeze
|
271
|
-
|
272
|
-
SYMBOL_METHODS = %w[
|
273
|
-
===
|
274
|
-
id2name
|
275
|
-
inspect
|
276
|
-
to_i
|
277
|
-
to_int
|
278
|
-
to_s
|
279
|
-
to_sym
|
280
|
-
].freeze
|
281
|
-
|
282
|
-
TRUECLASS_METHODS = %w[
|
283
|
-
&
|
284
|
-
to_s
|
285
|
-
^
|
286
|
-
|
|
287
|
-
].freeze
|
288
|
-
|
289
|
-
FALSECLASS_METHODS = %w[
|
290
|
-
&
|
291
|
-
to_s
|
292
|
-
^
|
293
|
-
|
|
294
|
-
].freeze
|
295
|
-
|
296
|
-
ENUMERABLE_METHODS = %w[
|
297
|
-
all?
|
298
|
-
any?
|
299
|
-
collect
|
300
|
-
detect
|
301
|
-
each_with_index
|
302
|
-
entries
|
303
|
-
find
|
304
|
-
find_all
|
305
|
-
grep
|
306
|
-
include?
|
307
|
-
inject
|
308
|
-
map
|
309
|
-
max
|
310
|
-
member?
|
311
|
-
min
|
312
|
-
partition
|
313
|
-
reject
|
314
|
-
select
|
315
|
-
sort
|
316
|
-
sort_by
|
317
|
-
to_a
|
318
|
-
zip
|
319
|
-
].freeze
|
320
|
-
|
321
|
-
STRING_METHODS = %w[
|
322
|
-
%
|
323
|
-
*
|
324
|
-
+
|
325
|
-
<<
|
326
|
-
<=>
|
327
|
-
==
|
328
|
-
=~
|
329
|
-
capitalize
|
330
|
-
capitalize!
|
331
|
-
casecmp
|
332
|
-
center
|
333
|
-
chomp
|
334
|
-
chomp!
|
335
|
-
chop
|
336
|
-
chop!
|
337
|
-
concat
|
338
|
-
count
|
339
|
-
crypt
|
340
|
-
delete
|
341
|
-
delete!
|
342
|
-
downcase
|
343
|
-
downcase!
|
344
|
-
dump
|
345
|
-
each
|
346
|
-
each_byte
|
347
|
-
each_line
|
348
|
-
empty?
|
349
|
-
eql?
|
350
|
-
gsub
|
351
|
-
gsub!
|
352
|
-
hash
|
353
|
-
hex
|
354
|
-
include?
|
355
|
-
index
|
356
|
-
initialize
|
357
|
-
initialize_copy
|
358
|
-
insert
|
359
|
-
inspect
|
360
|
-
intern
|
361
|
-
length
|
362
|
-
ljust
|
363
|
-
lines
|
364
|
-
lstrip
|
365
|
-
lstrip!
|
366
|
-
match
|
367
|
-
next
|
368
|
-
next!
|
369
|
-
oct
|
370
|
-
replace
|
371
|
-
reverse
|
372
|
-
reverse!
|
373
|
-
rindex
|
374
|
-
rjust
|
375
|
-
rstrip
|
376
|
-
rstrip!
|
377
|
-
scan
|
378
|
-
size
|
379
|
-
slice
|
380
|
-
slice!
|
381
|
-
split
|
382
|
-
squeeze
|
383
|
-
squeeze!
|
384
|
-
strip
|
385
|
-
strip!
|
386
|
-
start_with?
|
387
|
-
sub
|
388
|
-
sub!
|
389
|
-
succ
|
390
|
-
succ!
|
391
|
-
sum
|
392
|
-
swapcase
|
393
|
-
swapcase!
|
394
|
-
to_f
|
395
|
-
to_i
|
396
|
-
to_s
|
397
|
-
to_str
|
398
|
-
to_sym
|
399
|
-
tr
|
400
|
-
tr!
|
401
|
-
tr_s
|
402
|
-
tr_s!
|
403
|
-
upcase
|
404
|
-
upcase!
|
405
|
-
upto
|
406
|
-
[]
|
407
|
-
[]=
|
408
|
-
].freeze
|
409
|
-
end
|
410
17
|
end
|