Mercurial > hg > jdk9-shenandoah > nashorn
changeset 376:26a345c26e62
8015969: Needs to enforce and document that global "context" and "engine" can't be modified when running via jsr223
Reviewed-by: hannesw, jlaskey
author | sundar |
---|---|
date | Tue, 25 Jun 2013 17:31:19 +0530 |
parents | 51a5ee93d6bc |
children | 39e17373d8df |
files | docs/JavaScriptingProgrammersGuide.html src/jdk/nashorn/api/scripting/NashornScriptEngine.java src/jdk/nashorn/internal/runtime/AccessorProperty.java src/jdk/nashorn/internal/runtime/Property.java src/jdk/nashorn/internal/runtime/UserAccessorProperty.java test/script/basic/JDK-8015969.js |
diffstat | 6 files changed, 102 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/docs/JavaScriptingProgrammersGuide.html Mon Jun 24 19:06:01 2013 +0530 +++ b/docs/JavaScriptingProgrammersGuide.html Tue Jun 25 17:31:19 2013 +0530 @@ -227,6 +227,16 @@ it. Note that the syntax to access Java objects, methods and fields is dependent on the scripting language. JavaScript supports the most "natural" Java-like syntax.</p> +<p> +Nashorn script engine pre-defines two global variables named "context" +and "engine". The "context" variable is of type javax.script.ScriptContext +and refers to the current ScriptContext instance passed to script engine's +eval method. The "engine" variable is of type javax.script.ScriptEngine and +refers to the current nashorn script engine instance evaluating the script. +Both of these variables are non-writable, non-enumerable and non-configurable +- which implies script code can not write overwrite the value, for..loop iteration +on global object will not iterate these variables and these variables can not be +deleted by script. <pre><code> // <a href="source/ScriptVars.java">ScriptVars.java</a>
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Jun 24 19:06:01 2013 +0530 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Tue Jun 25 17:31:19 2013 +0530 @@ -71,6 +71,9 @@ private final ScriptEngineFactory factory; private final Context nashornContext; private final ScriptObject global; + // initialized bit late to be made 'final'. Property object for "context" + // property of global object + private Property contextProperty; // default options passed to Nashorn Options object private static final String[] DEFAULT_OPTIONS = new String[] { "-scripting", "-doe" }; @@ -281,13 +284,16 @@ nashornContext.initGlobal(newGlobal); + final int NON_ENUMERABLE_CONSTANT = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE; // current ScriptContext exposed as "context" - newGlobal.addOwnProperty("context", Property.NOT_ENUMERABLE, UNDEFINED); + // "context" is non-writable from script - but script engine still + // needs to set it and so save the context Property object + contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, UNDEFINED); // current ScriptEngine instance exposed as "engine". We added @SuppressWarnings("LeakingThisInConstructor") as // NetBeans identifies this assignment as such a leak - this is a false positive as we're setting this property // in the Global of a Context we just created - both the Context and the Global were just created and can not be // seen from another thread outside of this constructor. - newGlobal.addOwnProperty("engine", Property.NOT_ENUMERABLE, this); + newGlobal.addOwnProperty("engine", NON_ENUMERABLE_CONSTANT, this); // global script arguments with undefined value newGlobal.addOwnProperty("arguments", Property.NOT_ENUMERABLE, UNDEFINED); // file name default is null @@ -322,9 +328,10 @@ // scripts should see "context" and "engine" as variables private void setContextVariables(final ScriptContext ctxt) { - ctxt.setAttribute("context", ctxt, ScriptContext.ENGINE_SCOPE); final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt); - ctxtGlobal.set("context", ctxt, false); + // set "context" global variable via contextProperty - because this + // property is non-writable + contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false); Object args = ScriptObjectMirror.unwrap(ctxt.getAttribute("arguments"), ctxtGlobal); if (args == null || args == UNDEFINED) { args = ScriptRuntime.EMPTY_ARRAY;
--- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java Mon Jun 24 19:06:01 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java Tue Jun 25 17:31:19 2013 +0530 @@ -288,7 +288,7 @@ } @Override - protected void setObjectValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) { + public void setObjectValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) { if (isSpill()) { self.spill[getSlot()] = value; } else { @@ -303,7 +303,7 @@ } @Override - protected Object getObjectValue(final ScriptObject self, final ScriptObject owner) { + public Object getObjectValue(final ScriptObject self, final ScriptObject owner) { if (isSpill()) { return self.spill[getSlot()]; }
--- a/src/jdk/nashorn/internal/runtime/Property.java Mon Jun 24 19:06:01 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/Property.java Tue Jun 25 17:31:19 2013 +0530 @@ -363,7 +363,7 @@ * @param value the new property value * @param strict is this a strict setter? */ - protected abstract void setObjectValue(ScriptObject self, ScriptObject owner, Object value, boolean strict); + public abstract void setObjectValue(ScriptObject self, ScriptObject owner, Object value, boolean strict); /** * Set the Object value of this property from {@code owner}. This allows to bypass creation of the @@ -373,7 +373,7 @@ * @param owner the owner object * @return the property value */ - protected abstract Object getObjectValue(ScriptObject self, ScriptObject owner); + public abstract Object getObjectValue(ScriptObject self, ScriptObject owner); /** * Abstract method for retrieving the setter for the property. We do not know
--- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Mon Jun 24 19:06:01 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Tue Jun 25 17:31:19 2013 +0530 @@ -158,12 +158,12 @@ } @Override - protected Object getObjectValue(final ScriptObject self, final ScriptObject owner) { + public Object getObjectValue(final ScriptObject self, final ScriptObject owner) { return userAccessorGetter(owner, getGetterSlot(), self); } @Override - protected void setObjectValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) { + public void setObjectValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) { userAccessorSetter(owner, getSetterSlot(), strict ? getKey() : null, self, value); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8015969.js Tue Jun 25 17:31:19 2013 +0530 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8015969: Needs to enforce and document that global "context" and "engine" can't be modified when running via jsr223 + * + * @test + * @option -scripting + * @run + */ + +var m = new javax.script.ScriptEngineManager(); +var e = m.getEngineByName("nashorn"); + +e.eval(<<EOF + +'use strict'; + +try { + context = 444; + print("FAILED!! context write should have thrown error"); +} catch (e) { + if (! (e instanceof TypeError)) { + print("TypeError expected but got " + e); + } +} + +try { + engine = "hello"; + print("FAILED!! engine write should have thrown error"); +} catch (e) { + if (! (e instanceof TypeError)) { + print("TypeError expected but got " + e); + } +} + +try { + delete context; + print("FAILED!! context delete should have thrown error"); +} catch (e) { + if (! (e instanceof SyntaxError)) { + print("SyntaxError expected but got " + e); + } +} + +try { + delete engine; + print("FAILED!! engine delete should have thrown error"); +} catch (e) { + if (! (e instanceof SyntaxError)) { + print("SyntaxError expected but got " + e); + } +} + +EOF);