1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.runtime.test;
  27 
  28 import static org.testng.Assert.assertEquals;
  29 import static org.testng.Assert.fail;
  30 import java.io.File;
  31 import javax.script.ScriptEngine;
  32 import javax.script.ScriptException;
  33 import jdk.nashorn.api.scripting.ClassFilter;
  34 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
  35 import jdk.nashorn.api.scripting.URLReader;
  36 import jdk.nashorn.internal.test.framework.TestFinder;
  37 import org.testng.annotations.Test;
  38 
  39 @SuppressWarnings("javadoc")
  40 public class ClassFilterTest {
  41     private static final String NASHORN_CODE_CACHE = "nashorn.persistent.code.cache";
  42     private static final String CLASSFILTER_CODE_CACHE = System.getProperty("build.dir", "build") + "/classfilter_nashorn_code_cache";
  43 
  44     // @Test
  45     // This test takes too much time for basic "ant clean test" run.
  46     // Given that "allow-all-java-classes" is equivalent to no java class
  47     // filter and external tests don't access any java, not sure if this
  48     // test contributes much. We need faster "ant clean test" cycle for
  49     // developers.
  50     public void runExternalJsTest() {
  51         final String[] paths = new String[]{
  52                 "test/script/basic/compile-octane.js",
  53                 "test/script/basic/jquery.js",
  54                 "test/script/basic/prototype.js",
  55                 "test/script/basic/runsunspider.js",
  56                 "test/script/basic/underscore.js",
  57                 "test/script/basic/yui.js",
  58                 "test/script/basic/run-octane.js"
  59         };
  60         final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
  61         for (final String path : paths) {
  62             final ScriptEngine engine = factory.getScriptEngine(new String[]{"-scripting"}, getClass().getClassLoader(), getClassFilter());
  63             try {
  64                 engine.eval(new URLReader(new File(path).toURI().toURL()));
  65             } catch (final Exception e) {
  66                 fail("Script " + path + " fails with exception :" + e.getMessage());
  67             }
  68         }
  69     }
  70 
  71     @Test
  72     public void noJavaOptionTest() {
  73         final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
  74         final ScriptEngine engine = factory.getScriptEngine(new String[]{"--no-java"}, getClass().getClassLoader(), getClassFilter());
  75         try {
  76             engine.eval("var str = Java.type('java.lang.String');");
  77             fail("TypeError should have been thrown");
  78         } catch (final ScriptException e) {
  79             //emtpy
  80         }
  81         try {
  82             engine.eval("Java");
  83             fail("TypeError should have been thrown");
  84         } catch (final ScriptException e) {
  85             //emtpy
  86         }
  87         try {
  88             engine.eval("JavaImporter");
  89             fail("TypeError should have been thrown");
  90         } catch (final ScriptException e) {
  91             //emtpy
  92         }
  93         try {
  94             engine.eval("Packages");
  95             fail("TypeError should have been thrown");
  96         } catch (final ScriptException e) {
  97             //emtpy
  98         }
  99         try {
 100             engine.eval("com");
 101             fail("TypeError should have been thrown");
 102         } catch (final ScriptException e) {
 103             //emtpy
 104         }
 105         try {
 106             engine.eval("edu");
 107             fail("TypeError should have been thrown");
 108         } catch (final ScriptException e) {
 109             //emtpy
 110         }
 111         try {
 112             engine.eval("java");
 113             fail("TypeError should have been thrown");
 114         } catch (final ScriptException e) {
 115             //emtpy
 116         }
 117         try {
 118             engine.eval("javafx");
 119             fail("TypeError should have been thrown");
 120         } catch (final ScriptException e) {
 121             //emtpy
 122         }
 123         try {
 124             engine.eval("javax");
 125             fail("TypeError should have been thrown");
 126         } catch (final ScriptException e) {
 127             //emtpy
 128         }
 129         try {
 130             engine.eval("org");
 131             fail("TypeError should have been thrown");
 132         } catch (final ScriptException e) {
 133             //emtpy
 134         }
 135         try {
 136             assertEquals(engine.eval("Java = this[\"__LINE__\"]; Java === this[\"__LINE__\"]"), Boolean.TRUE);
 137         } catch (final ScriptException e) {
 138             fail("Unexpected exception", e);
 139         }
 140     }
 141 
 142     @Test
 143     public void securityTest() {
 144         if (System.getSecurityManager() == null) {
 145             return;
 146         }
 147 
 148         final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
 149         final ScriptEngine engine = factory.getScriptEngine(getClassFilter());
 150         try {
 151             engine.eval("var thread = Java.type('sun.misc.Unsafe')");
 152             fail("SecurityException should have been thrown");
 153         } catch (final Exception e) {
 154             //empty
 155         }
 156         try {
 157             engine.eval("var thread = new sun.misc.Unsafe()");
 158             fail("SecurityException should have been thrown");
 159         } catch (final Exception e) {
 160             //empty
 161         }
 162         try {
 163             engine.eval("var thread = Java.extend(sun.misc.Unsafe, {})");
 164             fail("TypeError should have been thrown");
 165         } catch (final Exception e) {
 166             //empty
 167         }
 168         try {
 169             engine.eval("java.lang.System.exit(0)");
 170             fail("SecurityException should have been thrown");
 171         } catch (final Exception e) {
 172             //empty
 173         }
 174 
 175     }
 176 
 177     @Test
 178     public void persistentCacheTest() {
 179         final String oldCodeCache = System.getProperty(NASHORN_CODE_CACHE);
 180         System.setProperty(NASHORN_CODE_CACHE, CLASSFILTER_CODE_CACHE);
 181         try {
 182             persistentCacheTestImpl();
 183         } finally {
 184             if (oldCodeCache != null) {
 185                 System.setProperty(NASHORN_CODE_CACHE, oldCodeCache);
 186             }
 187         }
 188     }
 189 
 190     private void persistentCacheTestImpl() {
 191         final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
 192         final ScriptEngine engine = factory.getScriptEngine(
 193               TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}),
 194                   getClass().getClassLoader(),
 195                   getClassFilter()
 196         );
 197         final String testScript = "var a = Java.type('java.lang.String');" + generateCodeForPersistentStore();
 198         try {
 199             engine.eval(testScript);
 200         } catch (final ScriptException exc) {
 201             fail(exc.getMessage());
 202         }
 203         final ScriptEngine engineSafe = factory.getScriptEngine(
 204                 TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}),
 205                 getClass().getClassLoader(),
 206                 new ClassFilter() {
 207                     @Override
 208                     public boolean exposeToScripts(final String s) {
 209                         return false;
 210                     }
 211                 }
 212         );
 213         try {
 214             engineSafe.eval(testScript);
 215             fail("ClassNotFoundException should have been thrown");
 216         } catch (final Exception exc) {
 217             if (!(exc.getCause() instanceof ClassNotFoundException)) {
 218                 fail("ClassNotFoundException expected, got " + exc.getClass());
 219             }
 220         }
 221     }
 222 
 223     private static String generateCodeForPersistentStore() {
 224         final StringBuilder stringBuilder = new StringBuilder();
 225         for (int i=0; i < 100; i++) {
 226             stringBuilder.append("function i")
 227                     .append(i)
 228                     .append("(y, z) { var x")
 229                     .append(i)
 230                     .append(" = ")
 231                     .append(i)
 232                     .append(";}");
 233         }
 234         return stringBuilder.toString();
 235     }
 236 
 237     private static ClassFilter getClassFilter() {
 238         return new ClassFilter() {
 239             @Override
 240             public boolean exposeToScripts(final String s) {
 241                 return true;
 242             }
 243         };
 244     }
 245 }