Commit ae11f20e authored by mvstanton's avatar mvstanton Committed by Commit bot

Scoping error caused crash in CallICNexus::StateFromFeedback

A sloppy mode eval call that establishes strict mode will leak that strictness
into the sloppy surrounding scope on recompile. This changes the structure
of the type feedback vector for the function and crashes follow.

The fix is straightforward.

BUG=491536, 503565
LOG=N

Review URL: https://codereview.chromium.org/1231343003

Cr-Commit-Position: refs/heads/master@{#29671}
parent 48584df5
......@@ -334,7 +334,8 @@ void Parser::SetCachedData(ParseInfo* info) {
FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
int pos, int end_pos) {
int pos, int end_pos,
LanguageMode language_mode) {
int materialized_literal_count = -1;
int expected_property_count = -1;
int parameter_count = 0;
......@@ -345,7 +346,7 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
: FunctionKind::kDefaultBaseConstructor;
Scope* function_scope = NewScope(scope, FUNCTION_SCOPE, kind);
function_scope->SetLanguageMode(
static_cast<LanguageMode>(scope->language_mode() | STRICT_BIT));
static_cast<LanguageMode>(language_mode | STRICT_BIT));
// Set start and end position to the same value
function_scope->set_start_position(pos);
function_scope->set_end_position(pos);
......@@ -795,8 +796,9 @@ Expression* ParserTraits::NewTargetExpression(Scope* scope,
Expression* ParserTraits::DefaultConstructor(bool call_super, Scope* scope,
int pos, int end_pos) {
return parser_->DefaultConstructor(call_super, scope, pos, end_pos);
int pos, int end_pos,
LanguageMode mode) {
return parser_->DefaultConstructor(call_super, scope, pos, end_pos, mode);
}
......@@ -873,10 +875,11 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral(
const AstRawString* name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_position, FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
FunctionLiteral::ArityRestriction arity_restriction,
LanguageMode language_mode, bool* ok) {
return parser_->ParseFunctionLiteral(
name, function_name_location, function_name_validity, kind,
function_token_position, type, arity_restriction, ok);
function_token_position, type, arity_restriction, language_mode, ok);
}
......@@ -1171,7 +1174,6 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
DCHECK(is_sloppy(scope->language_mode()) ||
is_strict(info->language_mode()));
DCHECK(info->language_mode() == shared_info->language_mode());
scope->SetLanguageMode(shared_info->language_mode());
FunctionLiteral::FunctionType function_type = shared_info->is_expression()
? (shared_info->is_anonymous()
? FunctionLiteral::ANONYMOUS_EXPRESSION
......@@ -1182,6 +1184,7 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
if (shared_info->is_arrow()) {
Scope* scope =
NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
scope->SetLanguageMode(shared_info->language_mode());
scope->set_start_position(shared_info->start_position());
ExpressionClassifier formals_classifier;
ParserFormalParameterParsingState parsing_state(scope);
......@@ -1227,12 +1230,13 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
} else if (shared_info->is_default_constructor()) {
result = DefaultConstructor(IsSubclassConstructor(shared_info->kind()),
scope, shared_info->start_position(),
shared_info->end_position());
shared_info->end_position(),
shared_info->language_mode());
} else {
result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
kSkipFunctionNameCheck, shared_info->kind(),
RelocInfo::kNoPosition, function_type,
FunctionLiteral::NORMAL_ARITY, &ok);
result = ParseFunctionLiteral(
raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck,
shared_info->kind(), RelocInfo::kNoPosition, function_type,
FunctionLiteral::NORMAL_ARITY, shared_info->language_mode(), &ok);
}
// Make sure the results agree.
DCHECK(ok == (result != NULL));
......@@ -2195,14 +2199,14 @@ Statement* Parser::ParseFunctionDeclaration(
bool is_strict_reserved = false;
const AstRawString* name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
FunctionLiteral* fun =
ParseFunctionLiteral(name, scanner()->location(),
FunctionLiteral* fun = ParseFunctionLiteral(
name, scanner()->location(),
is_strict_reserved ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
is_generator ? FunctionKind::kGeneratorFunction
: FunctionKind::kNormalFunction,
pos, FunctionLiteral::DECLARATION,
FunctionLiteral::NORMAL_ARITY, CHECK_OK);
pos, FunctionLiteral::DECLARATION, FunctionLiteral::NORMAL_ARITY,
language_mode(), CHECK_OK);
// Even if we're not at the top-level of the global or a function
// scope, we treat it as such and introduce the function with its
// initial value upon entering the corresponding scope.
......@@ -3920,7 +3924,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
const AstRawString* function_name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_pos, FunctionLiteral::FunctionType function_type,
FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
FunctionLiteral::ArityRestriction arity_restriction,
LanguageMode language_mode, bool* ok) {
// Function ::
// '(' FormalParameterList? ')' '{' FunctionBody '}'
//
......@@ -3976,12 +3981,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
Scope* declaration_scope = scope_->DeclarationScope();
Scope* original_declaration_scope = original_scope_->DeclarationScope();
Scope* scope = function_type == FunctionLiteral::DECLARATION &&
is_sloppy(language_mode()) &&
!allow_harmony_sloppy() &&
is_sloppy(language_mode) && !allow_harmony_sloppy() &&
(original_scope_ == original_declaration_scope ||
declaration_scope != original_declaration_scope)
? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
: NewScope(scope_, FUNCTION_SCOPE, kind);
scope->SetLanguageMode(language_mode);
ZoneList<Statement*>* body = NULL;
int materialized_literal_count = -1;
int expected_property_count = -1;
......@@ -4035,7 +4040,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
Variable* fvar = NULL;
Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
bool use_strict_const = is_strict(language_mode()) ||
bool use_strict_const = is_strict(language_mode) ||
(!allow_legacy_const() && allow_harmony_sloppy());
if (use_strict_const) {
fvar_init_op = Token::INIT_CONST;
......@@ -4118,8 +4123,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
fvar_init_op, kind, CHECK_OK);
materialized_literal_count = function_state.materialized_literal_count();
expected_property_count = function_state.expected_property_count();
}
if (is_strong(language_mode()) && IsSubclassConstructor(kind)) {
// Parsing the body may change the language mode in our scope.
language_mode = scope->language_mode();
if (is_strong(language_mode) && IsSubclassConstructor(kind)) {
if (!function_state.super_location().IsValid()) {
ReportMessageAt(function_name_location,
MessageTemplate::kStrongSuperCallMissing,
......@@ -4128,24 +4137,23 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
return nullptr;
}
}
}
// Validate name and parameter names. We can do this only after parsing the
// function, since the function can declare itself strict.
CheckFunctionName(language_mode(), function_name, function_name_validity,
CheckFunctionName(language_mode, function_name, function_name_validity,
function_name_location, CHECK_OK);
const bool use_strict_params =
!parsing_state.is_simple_parameter_list || IsConciseMethod(kind);
const bool allow_duplicate_parameters =
is_sloppy(language_mode()) && !use_strict_params;
ValidateFormalParameters(&formals_classifier, language_mode(),
is_sloppy(language_mode) && !use_strict_params;
ValidateFormalParameters(&formals_classifier, language_mode,
allow_duplicate_parameters, CHECK_OK);
if (is_strict(language_mode())) {
if (is_strict(language_mode)) {
CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
CHECK_OK);
}
if (is_strict(language_mode()) || allow_harmony_sloppy()) {
if (is_strict(language_mode) || allow_harmony_sloppy()) {
CheckConflictingVarDeclarations(scope, CHECK_OK);
}
}
......@@ -4534,8 +4542,8 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
int end_pos = scanner()->location().end_pos;
if (constructor == NULL) {
constructor =
DefaultConstructor(extends != NULL, block_scope, pos, end_pos);
constructor = DefaultConstructor(extends != NULL, block_scope, pos, end_pos,
block_scope->language_mode());
}
block_scope->set_end_position(end_pos);
......
......@@ -754,7 +754,7 @@ class ParserTraits {
Expression* NewTargetExpression(Scope* scope, AstNodeFactory* factory,
int pos);
Expression* DefaultConstructor(bool call_super, Scope* scope, int pos,
int end_pos);
int end_pos, LanguageMode language_mode);
Literal* ExpressionFromLiteral(Token::Value token, int pos, Scanner* scanner,
AstNodeFactory* factory);
Expression* ExpressionFromIdentifier(const AstRawString* name,
......@@ -796,7 +796,8 @@ class ParserTraits {
const AstRawString* name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_position, FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
FunctionLiteral::ArityRestriction arity_restriction,
LanguageMode language_mode, bool* ok);
V8_INLINE void SkipLazyFunctionBody(
int* materialized_literal_count, int* expected_property_count, bool* ok,
Scanner::BookmarkScope* bookmark = nullptr);
......@@ -1098,7 +1099,8 @@ class Parser : public ParserBase<ParserTraits> {
const AstRawString* name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_position, FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
FunctionLiteral::ArityRestriction arity_restriction,
LanguageMode language_mode, bool* ok);
ClassLiteral* ParseClassLiteral(const AstRawString* name,
......@@ -1138,7 +1140,7 @@ class Parser : public ParserBase<ParserTraits> {
// Factory methods.
FunctionLiteral* DefaultConstructor(bool call_super, Scope* scope, int pos,
int end_pos);
int end_pos, LanguageMode language_mode);
// Skip over a lazy function, either using cached data if we have it, or
// by parsing the function with PreParser. Consumes the ending }.
......
......@@ -93,10 +93,11 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral(
PreParserIdentifier name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_position, FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
FunctionLiteral::ArityRestriction arity_restriction,
LanguageMode language_mode, bool* ok) {
return pre_parser_->ParseFunctionLiteral(
name, function_name_location, function_name_validity, kind,
function_token_position, type, arity_restriction, ok);
function_token_position, type, arity_restriction, language_mode, ok);
}
......@@ -425,7 +426,8 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
is_generator ? FunctionKind::kGeneratorFunction
: FunctionKind::kNormalFunction,
pos, FunctionLiteral::DECLARATION,
FunctionLiteral::NORMAL_ARITY, CHECK_OK);
FunctionLiteral::NORMAL_ARITY, language_mode(),
CHECK_OK);
return Statement::FunctionDeclaration();
}
......@@ -1032,13 +1034,15 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
Identifier function_name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_pos, FunctionLiteral::FunctionType function_type,
FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
FunctionLiteral::ArityRestriction arity_restriction,
LanguageMode language_mode, bool* ok) {
// Function ::
// '(' FormalParameterList? ')' '{' FunctionBody '}'
// Parse function body.
bool outer_is_script_scope = scope_->is_script_scope();
Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
function_scope->SetLanguageMode(language_mode);
PreParserFactory factory(NULL);
FunctionState function_state(&function_state_, &scope_, function_scope, kind,
&factory);
......@@ -1072,23 +1076,26 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
}
Expect(Token::RBRACE, CHECK_OK);
// Parsing the body may change the language mode in our scope.
language_mode = function_scope->language_mode();
// Validate name and parameter names. We can do this only after parsing the
// function, since the function can declare itself strict.
CheckFunctionName(language_mode(), function_name, function_name_validity,
CheckFunctionName(language_mode, function_name, function_name_validity,
function_name_location, CHECK_OK);
const bool strict_formal_parameters =
!parsing_state.is_simple_parameter_list || IsConciseMethod(kind);
const bool allow_duplicate_parameters =
is_sloppy(language_mode()) && !strict_formal_parameters;
ValidateFormalParameters(&formals_classifier, language_mode(),
is_sloppy(language_mode) && !strict_formal_parameters;
ValidateFormalParameters(&formals_classifier, language_mode,
allow_duplicate_parameters, CHECK_OK);
if (is_strict(language_mode())) {
if (is_strict(language_mode)) {
int end_position = scanner()->location().end_pos;
CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
}
if (is_strong(language_mode()) && IsSubclassConstructor(kind)) {
if (is_strong(language_mode) && IsSubclassConstructor(kind)) {
if (!function_state.super_location().IsValid()) {
ReportMessageAt(function_name_location,
MessageTemplate::kStrongSuperCallMissing,
......
......@@ -1627,7 +1627,8 @@ class PreParserTraits {
PreParserIdentifier name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_position, FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
FunctionLiteral::ArityRestriction arity_restriction,
LanguageMode language_mode, bool* ok);
PreParserExpression ParseClassLiteral(PreParserIdentifier name,
Scanner::Location class_name_location,
......@@ -1775,7 +1776,8 @@ class PreParser : public ParserBase<PreParserTraits> {
Identifier name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_pos, FunctionLiteral::FunctionType function_type,
FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
FunctionLiteral::ArityRestriction arity_restriction,
LanguageMode language_mode, bool* ok);
void ParseLazyFunctionLiteralBody(bool* ok,
Scanner::BookmarkScope* bookmark = nullptr);
......@@ -2557,7 +2559,7 @@ ParserBase<Traits>::ParsePropertyDefinition(
value = this->ParseFunctionLiteral(
name, scanner()->location(), kSkipFunctionNameCheck, kind,
RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
FunctionLiteral::NORMAL_ARITY,
FunctionLiteral::NORMAL_ARITY, language_mode(),
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
return factory()->NewObjectLiteralProperty(name_expression, value,
......@@ -2590,7 +2592,7 @@ ParserBase<Traits>::ParsePropertyDefinition(
name, scanner()->location(), kSkipFunctionNameCheck, kind,
RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
language_mode(), CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
// Make sure the name expression is a string since we need a Name for
// Runtime_DefineAccessorPropertyUnchecked and since we can determine this
......@@ -3309,7 +3311,7 @@ ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier,
is_generator ? FunctionKind::kGeneratorFunction
: FunctionKind::kNormalFunction,
function_token_position, function_type, FunctionLiteral::NORMAL_ARITY,
CHECK_OK);
language_mode(), CHECK_OK);
} else if (peek() == Token::SUPER) {
const bool is_new = false;
result = ParseSuperExpression(is_new, classifier, CHECK_OK);
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-debug-as debug
if (this["debug"]) debug.Debug.setListener(function() {});
var source = "var outer = 0; function test() {'use strict'; outer = 1; } test(); print('ok');";
function test_function() { eval(source); }
assertDoesNotThrow(test_function);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Crashes without the fix for bug 503565.
function f() {}
function g() {}
function h() {
g()
}
(function() {
eval("\
\"use strict\";\
g = (function(x) {\
+Math.log(+Math.log((+(+x>0)), f(Math.log())))\
})\
")
})()
for (var j = 0; j < 999; j++) {
h()
}
......@@ -58,12 +58,12 @@ PASS new (class extends undefined { constructor () { this } }) threw exception T
PASS new (class extends undefined { constructor () { super(); } }) threw exception TypeError: Class extends value undefined is not a function or null.
PASS x = {}; new (class extends undefined { constructor () { return x; } }) threw exception TypeError: Class extends value undefined is not a function or null.
PASS y = 12; new (class extends undefined { constructor () { return y; } }) threw exception TypeError: Class extends value undefined is not a function or null.
FAIL class x {}; new (class extends null { constructor () { return new x; } }) instanceof x should be true. Threw exception TypeError: x is not a function
PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true
PASS new (class extends null { constructor () { this; } }) threw exception ReferenceError: this is not defined.
PASS new (class extends null { constructor () { super(); } }) threw exception TypeError: function () {} is not a constructor.
PASS x = {}; new (class extends null { constructor () { return x } }) is x
PASS y = 12; new (class extends null { constructor () { return y; } }) threw exception TypeError: Derived constructors may only return object or undefined.
FAIL class x {}; new (class extends null { constructor () { return new x; } }) instanceof x should be true. Threw exception TypeError: x is not a function
PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true
PASS x = null; Object.getPrototypeOf((class extends x { }).prototype) is null
PASS Object.prototype.isPrototypeOf(class { }) is true
PASS Function.prototype.isPrototypeOf(class { }) is true
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment