View Javadoc

1   package delight.rhinosandox.internal;
2   
3   import delight.rhinosandox.exceptions.ScriptCPUAbuseException;
4   import delight.rhinosandox.exceptions.ScriptDurationException;
5   import org.eclipse.xtext.xbase.lib.Exceptions;
6   import org.mozilla.javascript.Callable;
7   import org.mozilla.javascript.Context;
8   import org.mozilla.javascript.ContextFactory;
9   import org.mozilla.javascript.Scriptable;
10  
11  /**
12   * see http://www-archive.mozilla.org/rhino/apidocs/org/mozilla/javascript/ContextFactory.html
13   * 
14   * Also see https://github.com/flozano/rhino-sandbox-test/blob/master/src/main/java/com/flozano/rhino/sandbox/SandboxContextFactory.java
15   */
16  @SuppressWarnings("all")
17  public class SafeContext extends ContextFactory {
18    public static class CountContext extends Context {
19      private long startTime;
20      
21      private long instructions;
22    }
23    
24    private final static int INSTRUCTION_STEPS = 10000;
25    
26    public long maxRuntimeInMs;
27    
28    public int maxInstructions;
29    
30    @Override
31    public Context makeContext() {
32      final SafeContext.CountContext cx = new SafeContext.CountContext();
33      cx.setOptimizationLevel((-1));
34      cx.setInstructionObserverThreshold(SafeContext.INSTRUCTION_STEPS);
35      return cx;
36    }
37    
38    @Override
39    public boolean hasFeature(final Context cx, final int featureIndex) {
40      switch (featureIndex) {
41        case Context.FEATURE_NON_ECMA_GET_YEAR:
42          return true;
43        case Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME:
44          return true;
45        case Context.FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER:
46          return true;
47        case Context.FEATURE_PARENT_PROTO_PROPERTIES:
48          return false;
49      }
50      return super.hasFeature(cx, featureIndex);
51    }
52    
53    @Override
54    public void observeInstructionCount(final Context cx, final int instructionCount) {
55      try {
56        final SafeContext.CountContext mcx = ((SafeContext.CountContext) cx);
57        final long currentTime = System.currentTimeMillis();
58        if (((this.maxRuntimeInMs > 0) && ((currentTime - mcx.startTime) > this.maxRuntimeInMs))) {
59          throw new ScriptDurationException();
60        }
61        mcx.instructions = (mcx.instructions + SafeContext.INSTRUCTION_STEPS);
62        if (((this.maxInstructions > 0) && (mcx.instructions > this.maxInstructions))) {
63          throw new ScriptCPUAbuseException();
64        }
65      } catch (Throwable _e) {
66        throw Exceptions.sneakyThrow(_e);
67      }
68    }
69    
70    @Override
71    public Object doTopCall(final Callable callable, final Context cx, final Scriptable scope, final Scriptable thisObj, final Object[] args) {
72      final SafeContext.CountContext mcx = ((SafeContext.CountContext) cx);
73      long _currentTimeMillis = System.currentTimeMillis();
74      mcx.startTime = _currentTimeMillis;
75      mcx.instructions = 0;
76      return super.doTopCall(callable, cx, scope, thisObj, args);
77    }
78  }