xplenty-jruby_sandbox 0.2.4-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d06b08e73589246267426b4e93121d583a168c01
4
+ data.tar.gz: b72fcac1cc5956601d781cde42d74bae26516cf6
5
+ SHA512:
6
+ metadata.gz: cc6380715019cb8f27918bca1f673e7164d90631495ae1821fdf57ed31707cf16575dfc7c69c288cc01517447a1866e91a61f69de907c633c3238cfc1c7e7eca
7
+ data.tar.gz: d0ae61acb863f50a86df5dca25eb9630c74ceee64bbe6487aef1d54629ef890a045a796014dc4779b461b373e36a112d5964dc1dad1227ff7f1feb8634c06a3b
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ *.gem
2
+ .bundle
3
+ .ruby-gemset
4
+ Gemfile.lock
5
+ lib/sandbox/sandbox.jar
6
+ pkg/*
7
+ tags
8
+ tmp
9
+ .DS_Store
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ jruby-1.7.9
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - jruby-19mode
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # JRuby Sandbox Changelog
2
+
3
+ ## 0.2.3 (April 24, 2014)
4
+
5
+ * [SECURITY] Remove access to Object#java\_import.
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in jruby_sandbox.gemspec
4
+ gemspec
5
+
6
+ # this fork has some recent work done for 1.9, like File.foreach
7
+ gem 'fakefs', :git => 'git://github.com/codeschool/fakefs.git', :require => 'fakefs/safe', :ref => "6ae3212e3dab013b4b5e290d1aceba6466b30dec"
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2006 Ola Bini <ola@ologix.com>
2
+ Copyright (c) 2011 Dray Lacy and Eric Allam
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ JRuby Sandbox
2
+ =============
3
+
4
+ [![Build Status](https://travis-ci.org/omghax/jruby-sandbox.png?branch=master)](https://travis-ci.org/omghax/jruby-sandbox)
5
+
6
+ The JRuby sandbox is a reimplementation of \_why's freaky freaky sandbox
7
+ in JRuby, and is heavily based on [javasand][1] by Ola Bini, but updated
8
+ for JRuby 1.7.
9
+
10
+ ## Prerequisites
11
+
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:
20
+
21
+ rvm install jruby-1.7.6
22
+
23
+ ## Building
24
+
25
+ To build the JRuby extension, run `rake compile`. This will build the
26
+ `lib/sandbox/sandbox.jar` file, which `lib/sandbox.rb` loads.
27
+
28
+ ## Basic Usage
29
+
30
+ Sandbox gives you a self-contained JRuby interpreter in which to eval
31
+ code without polluting the host environment.
32
+
33
+ >> require "sandbox"
34
+ => true
35
+ >> sand = Sandbox::Full.new
36
+ => #<Sandbox::Full:0x46377e2a>
37
+ >> sand.eval("x = 1 + 2") # we've defined x in the sandbox
38
+ => 3
39
+ >> sand.eval("x")
40
+ => 3
41
+ >> x # but it hasn't leaked out into the host interpreter
42
+ NameError: undefined local variable or method `x' for #<Object:0x11cdc190>
43
+
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).
48
+
49
+ ## Sandbox::Safe usage
50
+
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.
54
+
55
+ >> require 'sandbox'
56
+ => true
57
+ >> sand = Sandbox.safe
58
+ => #<Sandbox::Safe:0x17072b90>
59
+ >> sand.eval %{`echo HELLO`}
60
+ => "HELLO\n"
61
+ >> sand.activate!
62
+ >> sand.eval %{`echo HELLO`}
63
+ Sandbox::SandboxException: NoMethodError: undefined method ``' for main:Object
64
+
65
+ Sandbox::Safe works by whitelisting methods to keep, and removing the rest.
66
+ Checkout sandbox.rb for which methods are kept.
67
+
68
+ Sandbox::Safe.activate! will also isolate the sandbox environment from the
69
+ filesystem using FakeFS.
70
+
71
+ >> require 'sandbox'
72
+ => true
73
+ >> s = Sandbox.safe
74
+ => #<Sandbox::Safe:0x3fdb8a73>
75
+ >> s.eval('Dir["/"]')
76
+ => ["/"]
77
+ >> s.eval('Dir["/*"]')
78
+ => ["/Applications", "/bin", "/cores", "/dev", etc.]
79
+ > s.activate!
80
+ >> s.eval('Dir["/*"]')
81
+ => []
82
+ > Dir['/*']
83
+ => ["/Applications", "/bin", "/cores", "/dev", etc.]
84
+
85
+ ## Known Issues / TODOs
86
+
87
+ * There is currently no timeout support, so it's possible for a
88
+ sandbox to loop indefinitely and block the host interpreter.
89
+
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
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/javaextensiontask'
5
+
6
+ Rake::JavaExtensionTask.new('sandbox') do |ext|
7
+ jruby_home = RbConfig::CONFIG['prefix']
8
+ ext.ext_dir = 'ext/java'
9
+ ext.lib_dir = 'lib/sandbox'
10
+ jars = ["#{jruby_home}/lib/jruby.jar"] + FileList['lib/*.jar']
11
+ ext.classpath = jars.map { |x| File.expand_path(x) }.join(':')
12
+ end
13
+
14
+ require 'rspec/core/rake_task'
15
+
16
+ RSpec::Core::RakeTask.new(:spec) do |t|
17
+ t.pattern = 'spec/**/*_spec.rb'
18
+ t.rspec_opts = ['--backtrace']
19
+ end
20
+
21
+ # Make sure the jar is up to date before running specs
22
+ task :spec => :compile
23
+
24
+ task :default => :spec
@@ -0,0 +1,35 @@
1
+ package sandbox;
2
+
3
+ import org.jruby.Ruby;
4
+ import org.jruby.RubyClass;
5
+ import org.jruby.anno.JRubyClass;
6
+ import org.jruby.anno.JRubyMethod;
7
+ import org.jruby.runtime.builtin.IRubyObject;
8
+ import org.jruby.runtime.Block;
9
+
10
+ @JRubyClass(name="BoxedClass")
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
+
20
+ @JRubyMethod(module=true, rest=true)
21
+ public static IRubyObject method_missing(IRubyObject recv, IRubyObject[] args, Block block) {
22
+ IRubyObject[] args2 = new IRubyObject[args.length - 1];
23
+ System.arraycopy(args, 1, args2, 0, args2.length);
24
+ String name = args[0].toString();
25
+
26
+ SandboxFull box = (SandboxFull) SandboxFull.getLinkedBox(recv);
27
+ return box.runMethod(recv, name, args2, block);
28
+ }
29
+
30
+ @JRubyMethod(name="new", meta=true, rest=true)
31
+ public static IRubyObject _new(IRubyObject recv, IRubyObject[] args, Block block) {
32
+ SandboxFull box = (SandboxFull) SandboxFull.getLinkedBox(recv);
33
+ return box.runMethod(recv, "new", args, block);
34
+ }
35
+ }
@@ -0,0 +1,317 @@
1
+ package sandbox;
2
+
3
+ import java.util.Collection;
4
+ import java.util.Map;
5
+
6
+ import org.jruby.Ruby;
7
+ import org.jruby.RubyClass;
8
+ import org.jruby.RubyInstanceConfig;
9
+ import org.jruby.RubyKernel;
10
+ import org.jruby.RubyModule;
11
+ import org.jruby.RubyObject;
12
+ import org.jruby.CompatVersion;
13
+ import org.jruby.anno.JRubyClass;
14
+ import org.jruby.anno.JRubyMethod;
15
+ import org.jruby.internal.runtime.methods.DynamicMethod;
16
+ import org.jruby.runtime.Block;
17
+ import org.jruby.runtime.ObjectAllocator;
18
+ import org.jruby.runtime.builtin.IRubyObject;
19
+ import org.jruby.common.IRubyWarnings;
20
+ import org.jruby.exceptions.RaiseException;
21
+ import org.jruby.runtime.DynamicScope;
22
+
23
+
24
+ @JRubyClass(name="Sandbox::Full")
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
+
32
+ private Ruby wrapped;
33
+ private DynamicScope currentScope;
34
+
35
+ protected SandboxFull(Ruby runtime, RubyClass type) {
36
+ super(runtime, type);
37
+ reload();
38
+ }
39
+
40
+ @JRubyMethod
41
+ public IRubyObject reload() {
42
+ RubyInstanceConfig cfg = new RubyInstanceConfig();
43
+ cfg.setObjectSpaceEnabled(getRuntime().getInstanceConfig().isObjectSpaceEnabled());
44
+ cfg.setInput(getRuntime().getInstanceConfig().getInput());
45
+ cfg.setOutput(getRuntime().getInstanceConfig().getOutput());
46
+ cfg.setError(getRuntime().getInstanceConfig().getError());
47
+ cfg.setCompatVersion(CompatVersion.RUBY1_9);
48
+ cfg.setScriptFileName("(sandbox)");
49
+
50
+ SandboxProfile profile = new SandboxProfile(this);
51
+ cfg.setProfile(profile);
52
+
53
+ wrapped = Ruby.newInstance(cfg);
54
+ currentScope = wrapped.getCurrentContext().getCurrentScope();
55
+
56
+ BoxedClass.createBoxedClassClass(wrapped);
57
+
58
+ return this;
59
+ }
60
+
61
+ @JRubyMethod(required=1)
62
+ public IRubyObject eval(IRubyObject str) {
63
+ try {
64
+ IRubyObject result = wrapped.evalScriptlet(str.asJavaString(), currentScope);
65
+ return unbox(result);
66
+ } catch (RaiseException e) {
67
+ String msg = e.getException().callMethod(wrapped.getCurrentContext(), "message").asJavaString();
68
+ String path = e.getException().type().getName();
69
+ RubyClass eSandboxException = (RubyClass) getRuntime().getClassFromPath("Sandbox::SandboxException");
70
+ throw new RaiseException(getRuntime(), eSandboxException, path + ": " + msg, false);
71
+ } catch (Exception e) {
72
+ e.printStackTrace();
73
+ getRuntime().getWarnings().warn(IRubyWarnings.ID.MISCELLANEOUS, "NativeException: " + e);
74
+ return getRuntime().getNil();
75
+ }
76
+ }
77
+
78
+ @JRubyMethod(name="import", required=1)
79
+ public IRubyObject _import(IRubyObject klass) {
80
+ if (!(klass instanceof RubyModule)) {
81
+ throw getRuntime().newTypeError(klass, getRuntime().getClass("Module"));
82
+ }
83
+ String name = ((RubyModule) klass).getName();
84
+ importClassPath(name, false);
85
+ return getRuntime().getNil();
86
+ }
87
+
88
+ @JRubyMethod(required=1)
89
+ public IRubyObject ref(IRubyObject klass) {
90
+ if (!(klass instanceof RubyModule)) {
91
+ throw getRuntime().newTypeError(klass, getRuntime().getClass("Module"));
92
+ }
93
+ String name = ((RubyModule) klass).getName();
94
+ importClassPath(name, true);
95
+ return getRuntime().getNil();
96
+ }
97
+
98
+ private RubyModule importClassPath(String path, final boolean link) {
99
+ RubyModule runtimeModule = getRuntime().getObject();
100
+ RubyModule wrappedModule = wrapped.getObject();
101
+
102
+ if (path.startsWith("#")) {
103
+ throw getRuntime().newArgumentError("can't import anonymous class " + path);
104
+ }
105
+
106
+ for (String name : path.split("::")) {
107
+ runtimeModule = (RubyModule) runtimeModule.getConstantAt(name);
108
+ // Create the module when it did not exist yet...
109
+ if (wrappedModule.const_defined_p(wrapped.getCurrentContext(), wrapped.newString(name)).isFalse()) {
110
+ // The BoxedClass takes the place of Object as top of the inheritance
111
+ // hierarchy. As a result, we can intercept all new instances that are
112
+ // created and all method_missing calls.
113
+ RubyModule sup = wrapped.getClass("BoxedClass");
114
+ if (!link && runtimeModule instanceof RubyClass) {
115
+ // If we're importing a class, recursively import all of its
116
+ // superclasses as well.
117
+ sup = importClassPath(runtimeModule.getSuperClass().getName(), true);
118
+ }
119
+
120
+ RubyClass klass = (RubyClass) sup;
121
+ if (wrappedModule == wrapped.getObject()) {
122
+
123
+ if (link || runtimeModule instanceof RubyClass) { // if this is a ref and not an import
124
+ wrappedModule = wrapped.defineClass(name, klass, klass.getAllocator());
125
+ } else {
126
+ wrappedModule = wrapped.defineModule(name);
127
+ }
128
+
129
+ } else {
130
+ if (runtimeModule instanceof RubyClass) {
131
+ wrappedModule = wrappedModule.defineClassUnder(name, klass, klass.getAllocator());
132
+ } else {
133
+ wrappedModule = wrappedModule.defineModuleUnder(name);
134
+ }
135
+
136
+ }
137
+ } else {
138
+ // ...or just resolve it, if it was already known
139
+ wrappedModule = (RubyModule) wrappedModule.getConstantAt(name);
140
+ }
141
+
142
+ // Check the consistency of the hierarchy
143
+ if (runtimeModule instanceof RubyClass) {
144
+ if (!link && !runtimeModule.getSuperClass().getName().equals(wrappedModule.getSuperClass().getName())) {
145
+ throw getRuntime().newTypeError("superclass mismatch for class " + runtimeModule.getSuperClass().getName());
146
+ }
147
+ }
148
+
149
+ if (link || runtimeModule instanceof RubyClass) {
150
+ linkObject(runtimeModule, wrappedModule);
151
+ } else {
152
+ copyMethods(runtimeModule, wrappedModule);
153
+ }
154
+ }
155
+
156
+ return runtimeModule;
157
+ }
158
+
159
+ private void copyMethods(RubyModule from, RubyModule to) {
160
+ to.getMethodsForWrite().putAll(from.getMethods());
161
+ to.getSingletonClass().getMethodsForWrite().putAll(from.getSingletonClass().getMethods());
162
+ }
163
+
164
+ @JRubyMethod(required=2)
165
+ public IRubyObject keep_methods(IRubyObject className, IRubyObject methods) {
166
+ RubyModule module = wrapped.getModule(className.asJavaString());
167
+ if (module != null) {
168
+ keepMethods(module, methods.convertToArray());
169
+ }
170
+ return methods;
171
+ }
172
+
173
+ @JRubyMethod(required=2)
174
+ public IRubyObject keep_singleton_methods(IRubyObject className, IRubyObject methods) {
175
+ RubyModule module = wrapped.getModule(className.asJavaString()).getSingletonClass();
176
+ if (module != null) {
177
+ keepMethods(module, methods.convertToArray());
178
+ }
179
+ return methods;
180
+ }
181
+
182
+ private void keepMethods(RubyModule module, Collection retain) {
183
+ for (Map.Entry<String, DynamicMethod> methodEntry : module.getMethods().entrySet()) {
184
+ String methodName = methodEntry.getKey();
185
+ if (!retain.contains(methodName)) {
186
+ removeMethod(module, methodName);
187
+ }
188
+ }
189
+ }
190
+
191
+ @JRubyMethod(required=2)
192
+ public IRubyObject remove_method(IRubyObject className, IRubyObject methodName) {
193
+ RubyModule module = wrapped.getModule(className.asJavaString());
194
+ if (module != null) {
195
+ removeMethod(module, methodName.asJavaString());
196
+ }
197
+ return getRuntime().getNil();
198
+ }
199
+
200
+ @JRubyMethod(required=2)
201
+ public IRubyObject remove_singleton_method(IRubyObject className, IRubyObject methodName) {
202
+ RubyModule module = wrapped.getModule(className.asJavaString()).getSingletonClass();
203
+ if (module != null) {
204
+ removeMethod(module, methodName.asJavaString());
205
+ }
206
+ return getRuntime().getNil();
207
+ }
208
+
209
+ private void removeMethod(RubyModule module, String methodName) {
210
+ // System.err.println("removing method " + methodName + " from " + module.inspect().asJavaString());
211
+ module.removeMethod(wrapped.getCurrentContext(), methodName);
212
+ }
213
+
214
+ @JRubyMethod(required=1)
215
+ public IRubyObject load(IRubyObject str) {
216
+ try {
217
+ wrapped.getLoadService().load(str.asJavaString(), true);
218
+ return getRuntime().getTrue();
219
+ } catch (RaiseException e) {
220
+ e.printStackTrace();
221
+ return getRuntime().getFalse();
222
+ }
223
+ }
224
+
225
+ @JRubyMethod(required=1)
226
+ public IRubyObject require(IRubyObject str) {
227
+ try {
228
+ IRubyObject result = RubyKernel.require(wrapped.getKernel(), wrapped.newString(str.asJavaString()), Block.NULL_BLOCK);
229
+ return unbox(result);
230
+ } catch (RaiseException e) {
231
+ e.printStackTrace();
232
+ return getRuntime().getFalse();
233
+ }
234
+ }
235
+
236
+ private IRubyObject unbox(IRubyObject obj) {
237
+ return box(obj);
238
+ }
239
+
240
+ private IRubyObject rebox(IRubyObject obj) {
241
+ return box(obj);
242
+ }
243
+
244
+ private IRubyObject box(IRubyObject obj) {
245
+ if (obj.isImmediate()) {
246
+ return cross(obj);
247
+ } else {
248
+ // If this object already existed and was returned from the wrapped
249
+ // runtime on an earlier occasion, it will already contain a link to its
250
+ // brother in the regular runtime and we can safely return that link.
251
+ IRubyObject link = getLinkedObject(obj);
252
+ if (!link.isNil()) {
253
+ IRubyObject box = getLinkedBox(obj);
254
+ if (box == this) return link;
255
+ }
256
+
257
+ // Is the class already known on both sides of the fence?
258
+ IRubyObject klass = constFind(obj.getMetaClass().getRealClass().getName());
259
+ link = getRuntime().getNil();
260
+ if (!klass.isNil()) {
261
+ link = getLinkedObject(klass);
262
+ }
263
+
264
+ if (link.isNil()) {
265
+ return cross(obj);
266
+ } else {
267
+ IRubyObject v = ((RubyClass)klass).allocate();
268
+ linkObject(obj, v);
269
+ return v;
270
+ }
271
+ }
272
+ }
273
+
274
+ private IRubyObject cross(IRubyObject obj) {
275
+ IRubyObject dumped = wrapped.getModule("Marshal").callMethod(wrapped.getCurrentContext(), "dump", obj);
276
+ return getRuntime().getModule("Marshal").callMethod(getRuntime().getCurrentContext(), "load", dumped);
277
+ }
278
+
279
+ protected static IRubyObject getLinkedObject(IRubyObject arg) {
280
+ IRubyObject object = arg.getRuntime().getNil();
281
+ if (arg.getInstanceVariables().hasInstanceVariable("__link__")) {
282
+ object = (IRubyObject) arg.getInstanceVariables().getInstanceVariable("__link__");
283
+ }
284
+ return object;
285
+ }
286
+
287
+ protected static IRubyObject getLinkedBox(IRubyObject arg) {
288
+ IRubyObject object = arg.getRuntime().getNil();
289
+ if (arg.getInstanceVariables().hasInstanceVariable("__box__")) {
290
+ object = (IRubyObject) arg.getInstanceVariables().getInstanceVariable("__box__");
291
+ }
292
+ return object;
293
+ }
294
+
295
+ private void linkObject(IRubyObject runtimeObject, IRubyObject wrappedObject) {
296
+ wrappedObject.getInstanceVariables().setInstanceVariable("__link__", runtimeObject);
297
+ wrappedObject.getInstanceVariables().setInstanceVariable("__box__", this);
298
+ }
299
+
300
+ private IRubyObject constFind(String path) {
301
+ try {
302
+ return wrapped.getClassFromPath(path);
303
+ } catch (Exception e) {
304
+ return wrapped.getNil();
305
+ }
306
+ }
307
+
308
+ protected IRubyObject runMethod(IRubyObject recv, String name, IRubyObject[] args, Block block) {
309
+ IRubyObject[] args2 = new IRubyObject[args.length];
310
+ for (int i = 0; i < args.length; i++) {
311
+ args2[i] = unbox(args[i]);
312
+ }
313
+ IRubyObject recv2 = unbox(recv);
314
+ IRubyObject result = recv2.callMethod(getRuntime().getCurrentContext(), name, args2, block);
315
+ return rebox(result);
316
+ }
317
+ }
@@ -0,0 +1,39 @@
1
+ package sandbox;
2
+
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;
8
+ import org.jruby.anno.JRubyMethod;
9
+ import org.jruby.runtime.builtin.IRubyObject;
10
+
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
+
31
+ @JRubyMethod(name="current", meta=true)
32
+ public static IRubyObject s_current(IRubyObject recv) {
33
+ Profile prof = recv.getRuntime().getProfile();
34
+ if (prof instanceof SandboxProfile) {
35
+ return ((SandboxProfile) prof).getSandbox();
36
+ }
37
+ return recv.getRuntime().getNil();
38
+ }
39
+ }
@@ -0,0 +1,22 @@
1
+ package sandbox;
2
+
3
+ import org.jruby.Profile;
4
+ import org.jruby.runtime.builtin.IRubyObject;
5
+
6
+ public class SandboxProfile implements Profile {
7
+ private IRubyObject sandbox;
8
+
9
+ public SandboxProfile(IRubyObject sandbox) {
10
+ this.sandbox = sandbox;
11
+ }
12
+
13
+ public IRubyObject getSandbox() {
14
+ return sandbox;
15
+ }
16
+
17
+ public boolean allowBuiltin(String name) { return true; }
18
+ public boolean allowClass(String name) { return true; }
19
+ public boolean allowModule(String name) { return true; }
20
+ public boolean allowLoad(String name) { return true; }
21
+ public boolean allowRequire(String name) { return true; }
22
+ }
@@ -0,0 +1,17 @@
1
+ package sandbox;
2
+
3
+ import java.io.IOException;
4
+
5
+ import org.jruby.Ruby;
6
+ import org.jruby.runtime.load.BasicLibraryService;
7
+
8
+ public class SandboxService implements BasicLibraryService {
9
+ public boolean basicLoad(Ruby runtime) throws IOException {
10
+ init(runtime);
11
+ return true;
12
+ }
13
+
14
+ private void init(Ruby runtime) {
15
+ SandboxModule.createSandboxModule(runtime);
16
+ }
17
+ }
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "sandbox/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "xplenty-jruby_sandbox"
7
+ s.version = Sandbox::VERSION
8
+ s.platform = "java"
9
+ s.authors = ["Dray Lacy", "Eric Allam", "Moty Michaely"]
10
+ s.email = ["dray@envylabs.com", "eric@envylabs.com", "moty.mi@gmail.com"]
11
+ s.homepage = "http://github.com/xplenty/jruby-sandbox"
12
+ s.summary = "Sandbox support for JRuby"
13
+ s.description = "A version of _why's Freaky Freaky Sandbox for JRuby."
14
+
15
+ s.rubyforge_project = "jruby_sandbox"
16
+
17
+ s.files = `git ls-files`.split("\n") + ["lib/sandbox/sandbox.jar"]
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
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"
28
+ end
@@ -0,0 +1,19 @@
1
+ # Alternate "safer" versions of Ruby methods. Mostly non-blocking.
2
+ [Fixnum, Bignum, Float].each do |klass|
3
+ klass.class_eval do
4
+ # A very weak version of pow, it doesn't work on Floats, but it's gonna
5
+ # fill the most common uses for now.
6
+ def **(x)
7
+ case x
8
+ when 0; 1
9
+ when 1; self
10
+ else
11
+ y = 1
12
+ while 0 <= (x -= 1) do
13
+ y *= self
14
+ end
15
+ y
16
+ end
17
+ end
18
+ end
19
+ end