8015969: Needs to enforce and document that global "context" and "engine" can't be modified when running via jsr223
Reviewed-by: hannesw, jlaskey
This commit is contained in:
parent
02e0b5c3f1
commit
249d0ae5b4
nashorn
docs
src/jdk/nashorn
api/scripting
internal/runtime
test/script/basic
@ -227,6 +227,16 @@ access the variable - for example, it can call public methods on
|
||||
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>
|
||||
|
||||
|
@ -71,6 +71,9 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
|
||||
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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
|
||||
// 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;
|
||||
|
@ -288,7 +288,7 @@ public class AccessorProperty extends Property {
|
||||
}
|
||||
|
||||
@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 @@ public class AccessorProperty extends Property {
|
||||
}
|
||||
|
||||
@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()];
|
||||
}
|
||||
|
@ -363,7 +363,7 @@ public abstract class Property {
|
||||
* @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 @@ public abstract class Property {
|
||||
* @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
|
||||
|
@ -158,12 +158,12 @@ public final class UserAccessorProperty extends Property {
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
|
75
nashorn/test/script/basic/JDK-8015969.js
Normal file
75
nashorn/test/script/basic/JDK-8015969.js
Normal file
@ -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);
|
Loading…
x
Reference in New Issue
Block a user