From: marja@chromium.org Date: Tue, 4 Feb 2014 09:47:30 +0000 (+0000) Subject: Tests for (pre)parse errors when "eval" and "arguments" are found in inappropriate... X-Git-Tag: upstream/4.7.83~10897 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9aa05b0997594e18bf38f46ce98ad4d5f6e4a408;p=platform%2Fupstream%2Fv8.git Tests for (pre)parse errors when "eval" and "arguments" are found in inappropriate places. In addition: - Fix a bug in parser discovered by the tests (prefix and postfix confused in an error message); the preparser had it right. - Unify the parser and preparser error locations when the name of a function is "eval" or "arguments. Now both point to the name. BUG=3126 LOG=N R=ulan@chromium.org Review URL: https://codereview.chromium.org/140543003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19050 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/parser.cc b/src/parser.cc index d525252..303c5ee 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -770,6 +770,7 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) { : FunctionLiteral::DECLARATION; bool ok = true; result = ParseFunctionLiteral(name, + Scanner::Location::invalid(), false, // Strict mode name already checked. shared_info->is_generator(), RelocInfo::kNoPosition, @@ -1679,6 +1680,7 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) { Handle name = ParseIdentifierOrStrictReservedWord( &is_strict_reserved, CHECK_OK); FunctionLiteral* fun = ParseFunctionLiteral(name, + scanner().location(), is_strict_reserved, is_generator, pos, @@ -3251,7 +3253,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) { if (!top_scope_->is_classic_mode()) { // Postfix expression operand in strict mode may not be eval or arguments. - CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK); + CheckStrictModeLValue(expression, "strict_lhs_postfix", CHECK_OK); } MarkAsLValue(expression); @@ -3400,14 +3402,17 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack, bool is_generator = allow_generators() && Check(Token::MUL); Handle name; bool is_strict_reserved_name = false; + Scanner::Location function_name_location = Scanner::Location::invalid(); if (peek_any_identifier()) { name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, CHECK_OK); + function_name_location = scanner().location(); } FunctionLiteral::FunctionType function_type = name.is_null() ? FunctionLiteral::ANONYMOUS_EXPRESSION : FunctionLiteral::NAMED_EXPRESSION; result = ParseFunctionLiteral(name, + function_name_location, is_strict_reserved_name, is_generator, function_token_position, @@ -3764,6 +3769,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { : GetSymbol(); FunctionLiteral* value = ParseFunctionLiteral(name, + scanner().location(), false, // reserved words are allowed here false, // not a generator RelocInfo::kNoPosition, @@ -4010,6 +4016,7 @@ class SingletonLogger : public ParserRecorder { FunctionLiteral* Parser::ParseFunctionLiteral( Handle function_name, + Scanner::Location function_name_location, bool name_is_strict_reserved, bool is_generator, int function_token_pos, @@ -4295,12 +4302,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral( // Validate strict mode. if (!top_scope_->is_classic_mode()) { if (IsEvalOrArguments(function_name)) { - int start_pos = scope->start_position(); - int position = function_token_pos != RelocInfo::kNoPosition - ? function_token_pos : (start_pos > 0 ? start_pos - 1 : start_pos); - Scanner::Location location = Scanner::Location(position, start_pos); - ReportMessageAt(location, - "strict_function_name", Vector::empty()); + ReportMessageAt(function_name_location, + "strict_function_name", + Vector::empty()); *ok = false; return NULL; } diff --git a/src/parser.h b/src/parser.h index 2d7c899..d415539 100644 --- a/src/parser.h +++ b/src/parser.h @@ -645,13 +645,14 @@ class Parser : public ParserBase { Statement* body); ZoneList* ParseArguments(bool* ok); - FunctionLiteral* ParseFunctionLiteral(Handle var_name, - bool name_is_reserved, - bool is_generator, - int function_token_position, - FunctionLiteral::FunctionType type, - bool* ok); - + FunctionLiteral* ParseFunctionLiteral( + Handle var_name, + Scanner::Location function_name_location, + bool name_is_reserved, + bool is_generator, + int function_token_position, + FunctionLiteral::FunctionType type, + bool* ok); // Magical syntax support. Expression* ParseV8Intrinsic(bool* ok); diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index 8fbd60d..c2651dc 100644 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -1345,3 +1345,145 @@ TEST(PreparserStrictOctal) { CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.", *exception); } + + +void VerifyPreParseAndParseNoError(v8::Handle source) { + v8::ScriptData* preparse = v8::ScriptData::PreCompile(source); + CHECK(!preparse->HasError()); + + v8::TryCatch try_catch; + v8::Script::Compile(source); + CHECK(!try_catch.HasCaught()); +} + + +void VerifyPreParseAndParseErrorMessages(v8::Handle source, + int error_location_beg, + int error_location_end, + const char* preparse_error_message, + const char* parse_error_message) { + v8::ScriptData* preparse = v8::ScriptData::PreCompile(source); + CHECK(preparse->HasError()); + i::ScriptDataImpl* pre_impl = + reinterpret_cast(preparse); + i::Scanner::Location error_location = pre_impl->MessageLocation(); + const char* message = pre_impl->BuildMessage(); + CHECK_EQ(0, strcmp(preparse_error_message, message)); + CHECK_EQ(error_location_beg, error_location.beg_pos); + CHECK_EQ(error_location_end, error_location.end_pos); + + v8::TryCatch try_catch; + v8::Script::Compile(source); + CHECK(try_catch.HasCaught()); + v8::String::Utf8Value exception(try_catch.Exception()); + CHECK_EQ(parse_error_message, *exception); + CHECK_EQ(error_location_beg, try_catch.Message()->GetStartPosition()); + CHECK_EQ(error_location_end, try_catch.Message()->GetEndPosition()); +} + + +TEST(ErrorsEvalAndArguments) { + // Tests that both preparsing and parsing produce the right kind of errors for + // using "eval" and "arguments" as identifiers. Without the strict mode, it's + // ok to use "eval" or "arguments" as identifiers. With the strict mode, it + // isn't. + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope handles(isolate); + v8::Local context = v8::Context::New(isolate); + v8::Context::Scope context_scope(context); + + const char* use_strict_prefix = "\"use strict\";\n"; + int prefix_length = i::StrLength(use_strict_prefix); + + const char* strict_var_name_preparse = "strict_var_name"; + const char* strict_var_name_parse = + "SyntaxError: Variable name may not be eval or arguments in strict mode"; + + const char* strict_catch_variable_preparse = "strict_catch_variable"; + const char* strict_catch_variable_parse = + "SyntaxError: Catch variable may not be eval or arguments in strict mode"; + + const char* strict_function_name_preparse = "strict_function_name"; + const char* strict_function_name_parse = + "SyntaxError: Function name may not be eval or arguments in strict mode"; + + const char* strict_param_name_preparse = "strict_param_name"; + const char* strict_param_name_parse = + "SyntaxError: Parameter name eval or arguments is not allowed in strict " + "mode"; + + const char* strict_lhs_assignment_preparse = "strict_lhs_assignment"; + const char* strict_lhs_assignment_parse = + "SyntaxError: Assignment to eval or arguments is not allowed in strict " + "mode"; + + const char* strict_lhs_prefix_preparse = "strict_lhs_prefix"; + const char* strict_lhs_prefix_parse = + "SyntaxError: Prefix increment/decrement may not have eval or arguments " + "operand in strict mode"; + + const char* strict_lhs_postfix_preparse = "strict_lhs_postfix"; + const char* strict_lhs_postfix_parse = + "SyntaxError: Postfix increment/decrement may not have eval or arguments " + "operand in strict mode"; + + struct TestCase { + const char* source; + int error_location_beg; + int error_location_end; + const char* preparse_error_message; + const char* parse_error_message; + } test_cases[] = { + {"var eval = 42;", 4, 8, strict_var_name_preparse, strict_var_name_parse}, + {"var arguments = 42;", 4, 13, strict_var_name_preparse, + strict_var_name_parse}, + {"var foo, eval;", 9, 13, strict_var_name_preparse, strict_var_name_parse}, + {"var foo, arguments;", 9, 18, strict_var_name_preparse, + strict_var_name_parse}, + {"try { } catch (eval) { }", 15, 19, strict_catch_variable_preparse, + strict_catch_variable_parse}, + {"try { } catch (arguments) { }", 15, 24, strict_catch_variable_preparse, + strict_catch_variable_parse}, + {"function eval() { }", 9, 13, strict_function_name_preparse, + strict_function_name_parse}, + {"function arguments() { }", 9, 18, strict_function_name_preparse, + strict_function_name_parse}, + {"function foo(eval) { }", 13, 17, strict_param_name_preparse, + strict_param_name_parse}, + {"function foo(arguments) { }", 13, 22, strict_param_name_preparse, + strict_param_name_parse}, + {"function foo(bar, eval) { }", 18, 22, strict_param_name_preparse, + strict_param_name_parse}, + {"function foo(bar, arguments) { }", 18, 27, strict_param_name_preparse, + strict_param_name_parse}, + {"eval = 1;", 0, 4, strict_lhs_assignment_preparse, + strict_lhs_assignment_parse}, + {"arguments = 1;", 0, 9, strict_lhs_assignment_preparse, + strict_lhs_assignment_parse}, + {"++eval;", 2, 6, strict_lhs_prefix_preparse, strict_lhs_prefix_parse}, + {"++arguments;", 2, 11, strict_lhs_prefix_preparse, + strict_lhs_prefix_parse}, + {"eval++;", 0, 4, strict_lhs_postfix_preparse, strict_lhs_postfix_parse}, + {"arguments++;", 0, 9, strict_lhs_postfix_preparse, + strict_lhs_postfix_parse}, + {NULL, 0, 0, NULL, NULL} + }; + + for (int i = 0; test_cases[i].source; ++i) { + v8::Handle source = + v8::String::NewFromUtf8(isolate, test_cases[i].source); + + VerifyPreParseAndParseNoError(source); + + v8::Handle strict_source = v8::String::Concat( + v8::String::NewFromUtf8(isolate, use_strict_prefix), + v8::String::NewFromUtf8(isolate, test_cases[i].source)); + + VerifyPreParseAndParseErrorMessages( + strict_source, + test_cases[i].error_location_beg + prefix_length, + test_cases[i].error_location_end + prefix_length, + test_cases[i].preparse_error_message, + test_cases[i].parse_error_message); + } +}