8026167: Class cache/reuse of 'eval' scripts results in ClassCastException in some cases
Reviewed-by: lagergren, jlaskey
This commit is contained in:
parent
16ce875fc6
commit
d5dda0a437
@ -162,7 +162,7 @@ enum CompilationPhase {
|
||||
LOWERING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED)) {
|
||||
@Override
|
||||
FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
|
||||
return (FunctionNode)fn.accept(new Lower());
|
||||
return (FunctionNode)fn.accept(new Lower(compiler));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,10 +86,13 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
|
||||
|
||||
private static final DebugLogger LOG = new DebugLogger("lower");
|
||||
|
||||
// needed only to get unique eval id from code installer
|
||||
private final Compiler compiler;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Lower() {
|
||||
Lower(final Compiler compiler) {
|
||||
super(new BlockLexicalContext() {
|
||||
|
||||
@Override
|
||||
@ -132,6 +135,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
|
||||
return block.setIsTerminal(this, false);
|
||||
}
|
||||
});
|
||||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -529,11 +533,15 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
|
||||
*/
|
||||
private String evalLocation(final IdentNode node) {
|
||||
final Source source = lc.getCurrentFunction().getSource();
|
||||
final int pos = node.position();
|
||||
return new StringBuilder().
|
||||
append(source.getName()).
|
||||
append('#').
|
||||
append(source.getLine(node.position())).
|
||||
append("<eval>").
|
||||
append(source.getLine(pos)).
|
||||
append(':').
|
||||
append(source.getColumn(pos)).
|
||||
append("<eval>@").
|
||||
append(compiler.getCodeInstaller().getUniqueEvalId()).
|
||||
toString();
|
||||
}
|
||||
|
||||
|
@ -68,4 +68,10 @@ public interface CodeInstaller<T> {
|
||||
* @return unique script id
|
||||
*/
|
||||
public long getUniqueScriptId();
|
||||
|
||||
/**
|
||||
* Get next unique eval id
|
||||
* @return unique eval id
|
||||
*/
|
||||
public long getUniqueEvalId();
|
||||
}
|
||||
|
@ -139,6 +139,11 @@ public final class Context {
|
||||
public long getUniqueScriptId() {
|
||||
return context.getUniqueScriptId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUniqueEvalId() {
|
||||
return context.getUniqueEvalId();
|
||||
}
|
||||
}
|
||||
|
||||
/** Is Context global debug mode enabled ? */
|
||||
@ -238,6 +243,9 @@ public final class Context {
|
||||
/** Unique id for script. Used only when --loader-per-compile=false */
|
||||
private final AtomicLong uniqueScriptId;
|
||||
|
||||
/** Unique id for 'eval' */
|
||||
private final AtomicLong uniqueEvalId;
|
||||
|
||||
private static final ClassLoader myLoader = Context.class.getClassLoader();
|
||||
private static final StructureLoader sharedLoader;
|
||||
|
||||
@ -320,6 +328,7 @@ public final class Context {
|
||||
this.uniqueScriptId = new AtomicLong();
|
||||
}
|
||||
this.errors = errors;
|
||||
this.uniqueEvalId = new AtomicLong();
|
||||
|
||||
// if user passed -classpath option, make a class loader with that and set it as
|
||||
// thread context class loader so that script can access classes from that path.
|
||||
@ -954,6 +963,10 @@ public final class Context {
|
||||
}, CREATE_LOADER_ACC_CTXT);
|
||||
}
|
||||
|
||||
private long getUniqueEvalId() {
|
||||
return uniqueEvalId.getAndIncrement();
|
||||
}
|
||||
|
||||
private long getUniqueScriptId() {
|
||||
return uniqueScriptId.getAndIncrement();
|
||||
}
|
||||
|
@ -61,3 +61,22 @@ Object.defineProperty(this, "fail", {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(this, "printError", {
|
||||
configuable: true,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: function (e) {
|
||||
var msg = e.message;
|
||||
var str = e.name + ':';
|
||||
if (e.lineNumber > 0) {
|
||||
str += e.lineNumber + ':';
|
||||
}
|
||||
if (e.columnNumber > 0) {
|
||||
str += e.columnNumber + ':';
|
||||
}
|
||||
str += msg.substring(msg.indexOf(' ') + 1);
|
||||
print(str);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -36,7 +36,7 @@ function checkObjLiteral(str) {
|
||||
if (! (e instanceof SyntaxError)) {
|
||||
fail("expected SyntaxError, got " + e);
|
||||
}
|
||||
print(e.message.replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
test/script/basic/JDK-8019508.js#33<eval>:1:2 Expected property id but found ,
|
||||
SyntaxError:33:Expected property id but found ,
|
||||
({,})
|
||||
^
|
||||
test/script/basic/JDK-8019508.js#33<eval>:1:2 Expected property id but found ,
|
||||
SyntaxError:33:Expected property id but found ,
|
||||
({, a:2 })
|
||||
^
|
||||
test/script/basic/JDK-8019508.js#33<eval>:1:6 Expected property id but found ,
|
||||
SyntaxError:33:Expected property id but found ,
|
||||
({a:3,,})
|
||||
^
|
||||
test/script/basic/JDK-8019508.js#33<eval>:1:6 Expected comma but found ident
|
||||
SyntaxError:33:Expected comma but found ident
|
||||
({a:3 b:2}
|
||||
^
|
||||
|
@ -33,7 +33,7 @@ function check(str) {
|
||||
eval(str);
|
||||
fail("SyntaxError expected for: " + str);
|
||||
} catch (e) {
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found +
|
||||
SyntaxError:33:Expected l-value but found +
|
||||
++ +3
|
||||
^
|
||||
SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found -
|
||||
SyntaxError:33:Expected l-value but found -
|
||||
++ -7
|
||||
^
|
||||
SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found +
|
||||
SyntaxError:33:Expected l-value but found +
|
||||
-- +2
|
||||
^
|
||||
SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found -
|
||||
SyntaxError:33:Expected l-value but found -
|
||||
-- -8
|
||||
^
|
||||
|
@ -33,7 +33,7 @@ try {
|
||||
eval('"" ~ ""');
|
||||
print("FAILED: SyntaxError expected for: \"\" ~ \"\"");
|
||||
} catch (e) {
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
||||
// Used to crash instead of SyntaxError
|
||||
@ -41,7 +41,7 @@ try {
|
||||
eval("function() { if (1~0) return 0; return 1 }");
|
||||
print("FAILED: SyntaxError expected for: if (1~0) ");
|
||||
} catch (e) {
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
||||
// The following are valid, but used to crash
|
||||
|
@ -1,6 +1,6 @@
|
||||
SyntaxError: test/script/basic/JDK-8019791.js#33<eval>:1:3 Expected ; but found ~
|
||||
SyntaxError:33:Expected ; but found ~
|
||||
"" ~ ""
|
||||
^
|
||||
SyntaxError: test/script/basic/JDK-8019791.js#41<eval>:1:18 Expected ) but found ~
|
||||
SyntaxError:41:Expected ) but found ~
|
||||
function() { if (1~0) return 0; return 1 }
|
||||
^
|
||||
|
@ -32,5 +32,5 @@ try {
|
||||
eval("for each(var v=0;false;);");
|
||||
print("FAILED: for each(var v=0; false;); should have thrown error");
|
||||
} catch (e) {
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
SyntaxError: test/script/basic/JDK-8019805.js#32<eval>:1:16 for each can only be used with for..in
|
||||
SyntaxError:32:for each can only be used with for..in
|
||||
for each(var v=0;false;);
|
||||
^
|
||||
|
50
nashorn/test/script/basic/JDK-8026167.js
Normal file
50
nashorn/test/script/basic/JDK-8026167.js
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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-8026167: Class cache/reuse of 'eval' scripts results in ClassCastException in some cases.
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
var m = new javax.script.ScriptEngineManager();
|
||||
var e = m.getEngineByName('js');
|
||||
|
||||
// leave the whitespace - need both eval("e") at same column for this test!
|
||||
|
||||
e.eval('function f(e) { eval("e") } f()');
|
||||
e.eval('function f() { var e = 33; eval("e") } f()');
|
||||
|
||||
function f() {
|
||||
Function.call.call(function x() { eval("x") }); eval("x")
|
||||
}
|
||||
|
||||
try {
|
||||
f();
|
||||
fail("Should have thrown ReferenceError");
|
||||
} catch (e) {
|
||||
if (! (e instanceof ReferenceError)) {
|
||||
fail("ReferenceError expected but got " + e);
|
||||
}
|
||||
}
|
@ -35,5 +35,5 @@ try {
|
||||
if (! (e instanceof SyntaxError)) {
|
||||
fail("#2 expected SyntaxError got " + e);
|
||||
}
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
SyntaxError: test/script/basic/NASHORN-100.js#32<eval>:1:0 Invalid return statement
|
||||
SyntaxError:32:Invalid return statement
|
||||
return;
|
||||
^
|
||||
|
@ -40,15 +40,13 @@ for (var i = 0; i < 3; i++) {
|
||||
try {
|
||||
eval(src);
|
||||
} catch (e) {
|
||||
var location = e.fileName ? e.fileName.slice(-9) : "unknown source";
|
||||
print(e.name, "@", location);
|
||||
printError(e);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < 3; i++) {
|
||||
try {
|
||||
eval(src);
|
||||
} catch (e) {
|
||||
var location = e.fileName ? e.fileName.slice(-9) : "unknown source";
|
||||
print(e.name, "@", location);
|
||||
printError(e);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
hello
|
||||
hello
|
||||
hello
|
||||
TypeError @ #41<eval>
|
||||
TypeError @ #41<eval>
|
||||
TypeError @ #41<eval>
|
||||
TypeError @ #49<eval>
|
||||
TypeError @ #49<eval>
|
||||
TypeError @ #49<eval>
|
||||
TypeError:1:read property "foo" from undefined
|
||||
TypeError:1:read property "foo" from undefined
|
||||
TypeError:1:read property "foo" from undefined
|
||||
TypeError:1:read property "foo" from undefined
|
||||
TypeError:1:read property "foo" from undefined
|
||||
TypeError:1:read property "foo" from undefined
|
||||
|
@ -31,11 +31,11 @@
|
||||
try {
|
||||
eval("print(.foo)");
|
||||
} catch (e) {
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
eval(".bar = 3423;");
|
||||
} catch (e) {
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
SyntaxError: test/script/basic/NASHORN-40.js#32<eval>:1:6 Expected an operand but found .
|
||||
SyntaxError:32:Expected an operand but found .
|
||||
print(.foo)
|
||||
^
|
||||
SyntaxError: test/script/basic/NASHORN-40.js#38<eval>:1:0 Expected an operand but found .
|
||||
SyntaxError:38:Expected an operand but found .
|
||||
.bar = 3423;
|
||||
^
|
||||
|
@ -35,28 +35,28 @@ for (i in literals) {
|
||||
eval(literals[i] + "++");
|
||||
print("ERROR!! post increment : " + literals[i]);
|
||||
} catch (e) {
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
eval(literals[i] + "--");
|
||||
print("ERROR!! post decrement : " + literals[i]);
|
||||
} catch (e) {
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
eval("++" + literals[i]);
|
||||
print("ERROR!! pre increment : " + literals[i]);
|
||||
} catch (e) {
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
eval("--" + literals[i]);
|
||||
print("ERROR!! pre decrement : " + literals[i]);
|
||||
} catch (e) {
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,72 +1,72 @@
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:35:Invalid left hand side for assignment
|
||||
1++
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:42:Invalid left hand side for assignment
|
||||
1--
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:49:Invalid left hand side for assignment
|
||||
++1
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:56:Invalid left hand side for assignment
|
||||
--1
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:35:Invalid left hand side for assignment
|
||||
0++
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:42:Invalid left hand side for assignment
|
||||
0--
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:49:Invalid left hand side for assignment
|
||||
++0
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:56:Invalid left hand side for assignment
|
||||
--0
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:35:Invalid left hand side for assignment
|
||||
3.14++
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:42:Invalid left hand side for assignment
|
||||
3.14--
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:49:Invalid left hand side for assignment
|
||||
++3.14
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:56:Invalid left hand side for assignment
|
||||
--3.14
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:35:Invalid left hand side for assignment
|
||||
true++
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:42:Invalid left hand side for assignment
|
||||
true--
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:49:Invalid left hand side for assignment
|
||||
++true
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:56:Invalid left hand side for assignment
|
||||
--true
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:35:Invalid left hand side for assignment
|
||||
false++
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:42:Invalid left hand side for assignment
|
||||
false--
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:49:Invalid left hand side for assignment
|
||||
++false
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:56:Invalid left hand side for assignment
|
||||
--false
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:35:Invalid left hand side for assignment
|
||||
null++
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
|
||||
ReferenceError:42:Invalid left hand side for assignment
|
||||
null--
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:49:Invalid left hand side for assignment
|
||||
++null
|
||||
^
|
||||
ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
|
||||
ReferenceError:56:Invalid left hand side for assignment
|
||||
--null
|
||||
^
|
||||
|
@ -34,7 +34,7 @@ try {
|
||||
if (! (e instanceof SyntaxError)) {
|
||||
fail("syntax error expected here got " + e);
|
||||
}
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
@ -43,5 +43,5 @@ try {
|
||||
if (! (e instanceof SyntaxError)) {
|
||||
fail("syntax error expected here got " + e);
|
||||
}
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
SyntaxError: test/script/basic/NASHORN-98.js#32<eval>:1:13 Expected comma but found decimal
|
||||
SyntaxError:32:Expected comma but found decimal
|
||||
var x = [ 23 34 ]
|
||||
^
|
||||
SyntaxError: test/script/basic/NASHORN-98.js#41<eval>:1:18 Expected comma but found ident
|
||||
SyntaxError:41:Expected comma but found ident
|
||||
var x = { foo: 33 bar: 'hello' }
|
||||
^
|
||||
|
@ -69,5 +69,5 @@ try {
|
||||
eval("print('hello)");
|
||||
} catch (e) {
|
||||
print("is syntax error? " + (e instanceof SyntaxError));
|
||||
print(e.toString().replace(/\\/g, '/'));
|
||||
printError(e);
|
||||
}
|
||||
|
@ -10,6 +10,6 @@ eval.length 1
|
||||
100
|
||||
3300
|
||||
is syntax error? true
|
||||
SyntaxError: test/script/basic/eval.js#69<eval>:1:13 Missing close quote
|
||||
SyntaxError:69:Missing close quote
|
||||
print('hello)
|
||||
^
|
||||
|
Loading…
x
Reference in New Issue
Block a user