提交 ea2cfe6c 编写于 作者: H hannesw

8027302: Identifiers containing unicode escapes are not recognized as reserved words

Reviewed-by: jlaskey, sundar
上级 45cf8107
......@@ -477,4 +477,14 @@ public final class IdentNode extends Expression implements PropertyKey, Function
public IdentNode setIsDestructuredParameter() {
return new IdentNode(this, name, type, flags | DESTRUCTURED_PARAMETER, programPoint, conversion);
}
/**
* Checks whether the source code for this ident contains a unicode escape sequence by comparing
* the length of its name with its length in source code.
*
* @return true if ident source contains a unicode escape sequence
*/
public boolean containsEscapes() {
return Token.descLength(getToken()) != name.length();
}
}
......@@ -786,15 +786,9 @@ public class Lexer extends Scanner {
if (ch0 == '\\' && ch1 == 'u') {
skip(2);
final int ch = hexSequence(4, TokenType.IDENT);
if (isWhitespace((char)ch)) {
return null;
}
if (ch < 0) {
sb.append('\\');
sb.append('u');
} else {
sb.append((char)ch);
}
assert ! isWhitespace((char)ch);
assert ch >= 0;
sb.append((char)ch);
} else {
// Add regular character.
sb.append(ch0);
......@@ -994,9 +988,6 @@ public class Lexer extends Scanner {
if (ch0 == '\\') {
type = ESCSTRING;
skip(1);
if (! isEscapeCharacter(ch0)) {
error(Lexer.message("invalid.escape.char"), STRING, position, limit);
}
if (isEOL(ch0)) {
// Multiline string literal
skipEOL(false);
......@@ -1093,9 +1084,6 @@ public class Lexer extends Scanner {
} else if (ch0 == '\\') {
skip(1);
// EscapeSequence
if (!isEscapeCharacter(ch0)) {
error(Lexer.message("invalid.escape.char"), TEMPLATE, position, limit);
}
if (isEOL(ch0)) {
// LineContinuation
skipEOL(false);
......@@ -1114,16 +1102,6 @@ public class Lexer extends Scanner {
error(Lexer.message("missing.close.quote"), TEMPLATE, position, limit);
}
/**
* Is the given character a valid escape char after "\" ?
*
* @param ch character to be checked
* @return if the given character is valid after "\"
*/
protected boolean isEscapeCharacter(final char ch) {
return true;
}
/**
* Convert string to number.
*
......
......@@ -1472,12 +1472,7 @@ public class Parser extends AbstractParser implements Loggable {
*/
private void verifyIdent(final IdentNode ident, final String contextString) {
verifyStrictIdent(ident, contextString);
if (isES6()) {
final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length());
if (tokenType != IDENT && tokenType.getKind() != TokenKind.FUTURESTRICT) {
throw error(expectMessage(IDENT));
}
}
checkEscapedKeyword(ident);
}
/**
......@@ -1502,6 +1497,18 @@ public class Parser extends AbstractParser implements Loggable {
}
}
/**
* ES6 11.6.2: A code point in a ReservedWord cannot be expressed by a | UnicodeEscapeSequence.
*/
private void checkEscapedKeyword(final IdentNode ident) {
if (isES6() && ident.containsEscapes()) {
final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length());
if (tokenType != IDENT && !(tokenType.getKind() == TokenKind.FUTURESTRICT && !isStrictMode)) {
throw error(AbstractParser.message("keyword.escaped.character"), ident.getToken());
}
}
}
/*
* VariableStatement :
* var VariableDeclarationList ;
......@@ -2646,7 +2653,7 @@ public class Parser extends AbstractParser implements Loggable {
});
} else {
// ECMA 12.4.1 strict mode restrictions
verifyStrictIdent((IdentNode) exception, "catch argument");
verifyIdent((IdentNode) exception, "catch argument");
}
......@@ -2761,6 +2768,7 @@ public class Parser extends AbstractParser implements Loggable {
break;
}
detectSpecialProperty(ident);
checkEscapedKeyword(ident);
return ident;
case OCTAL_LEGACY:
if (isStrictMode) {
......@@ -3404,6 +3412,7 @@ public class Parser extends AbstractParser implements Loggable {
// Catch special functions.
if (lhs instanceof IdentNode) {
detectSpecialFunction((IdentNode)lhs);
checkEscapedKeyword((IdentNode)lhs);
}
lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
......@@ -3779,7 +3788,7 @@ public class Parser extends AbstractParser implements Loggable {
expect(IDENT);
}
name = getIdent();
verifyStrictIdent(name, "function name");
verifyIdent(name, "function name");
} else if (isStatement) {
// Nashorn extension: anonymous function statements.
// Do not allow anonymous function statement if extensions
......@@ -4871,7 +4880,7 @@ public class Parser extends AbstractParser implements Loggable {
final String contextString = "function parameter";
if (param instanceof IdentNode) {
final IdentNode ident = (IdentNode)param;
verifyStrictIdent(ident, contextString);
verifyIdent(ident, contextString);
final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
if (currentFunction != null) {
currentFunction.addParameterBinding(ident);
......
......@@ -62,6 +62,7 @@ parser.error.regex.syntax={0}
parser.error.trailing.comma.in.json=Trailing comma is not allowed in JSON
parser.error.missing.const.assignment=Missing assignment to constant "{0}"
parser.error.unterminated.template.expression=Expected } after expression in template literal
parser.error.keyword.escaped.character=Keyword must not contain escaped characters
# ES6 mode error messages
parser.error.multiple.constructors=Class contains more than one constructor
......
/*
* Copyright (c) 2017, 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-8027302: Identifiers containing unicode escapes are not recognized as reserved words
*
* @test
* @run
*/
// keywords containing escapes
try {
eval("v\\u0061r i;");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("\\u0069f (true) ;");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof ReferenceError); // no SyntaxError in ES5
}
try {
eval("if (true) ; \\u0065lse ;");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof ReferenceError); // no SyntaxError in ES5
}
try {
eval("f\\u0075nction x() {}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var f = f\\u0075nction() {}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var o = { f: f\\u0075nction() {}}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var a = [f\\u0075nction() {}]");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
// keywords as identifiers, with and without escapes
try {
eval("function break() {}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("function bre\\u0061k() {}");
} catch (e) {
fail("Unexpected error");
}
try {
eval("function f(break) {}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("function f(bre\\u0061k) {}");
} catch (e) {
fail("Unexpected error");
}
try {
eval("var break = 3");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("'use strict'; var break = 3");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var bre\\u0061k = 3");
} catch (e) {
fail("Unexpected error");
}
try {
eval("'use strict'; var bre\\u0061k = 3");
} catch (e) {
fail("Unexpected error");
}
try {
eval("var package = 3");
} catch (e) {
fail("Unexpected error");
}
try {
eval("'use strict'; var package = 3");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var p\\u0061ckage = 3");
} catch (e) {
fail("Unexpected error");
}
try {
eval("'use strict'; var p\\u0061ckage = 3");
} catch (e) {
fail("Unexpected error");
}
/*
* Copyright (c) 2017, 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-8027302: Identifiers containing unicode escapes are not recognized as reserved words
*
* @test
* @run
* @option --language=es6
*/
// keywords containing escapes
try {
eval("v\\u0061r i;");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("\\u0069f (true) ;");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("if (true) ; \\u0065lse ;");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("f\\u0075nction x() {}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var f = f\\u0075nction() {}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var o = { f: f\\u0075nction() {}}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var a = [f\\u0075nction() {}]");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
// keywords as identifiers, with and without escapes
try {
eval("function break() {}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("function bre\\u0061k() {}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("function f(break) {}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("function f(bre\\u0061k) {}");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var break = 3");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("'use strict'; var break = 3");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var bre\\u0061k = 3");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("'use strict'; var bre\\u0061k = 3");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var package = 3");
} catch (e) {
fail("Unexpected error");
}
try {
eval("'use strict'; var package = 3");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
try {
eval("var p\\u0061ckage = 3");
} catch (e) {
fail("Unexpected error");
}
try {
eval("'use strict'; var p\\u0061ckage = 3");
fail("Expected error");
} catch (e) {
Assert.assertTrue(e instanceof SyntaxError);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册