Commit 3c3ce1bc authored by aperez's avatar aperez Committed by Commit bot

Parser: Fix crash on stack overflow when lazy-parsing arrow functions

The problem manifests itself when parsing manages to return something
meaningful in the presence of a stack overflow. This happens because
calling ParserBase::Next() will still return one valid token on stack
overflow, before starting to return invalid tokens.

Take the following input as example:

        a.map(v => v + 1);
              | |
       already   next token
        parsed   (which will be an invalid token
  (identifier)   because of a stack overflow)

The "v" may have been already parsed into a VariableProxy, then if a
stack overflow occurs, next token will be an invalid token (instead
of Token::ARROW), but the parser will return the VariableProxy.

This always happens when lazy-parsing arrow functions, so the position
in the input stream where the the arrow function code ends is known.
This fix adds a check that ensures that parsing ended at the end
position of the arrow function.

BUG=465671
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#27325}
parent bac0853d
......@@ -1145,8 +1145,24 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
// from creating unresolved variables in already-resolved scopes.
parsing_lazy_arrow_parameters_ = true;
Expression* expression = ParseExpression(false, &ok);
DCHECK(expression->IsFunctionLiteral());
result = expression->AsFunctionLiteral();
if (ok) {
// Scanning must end at the same position that was recorded
// previously. If not, parsing has been interrupted due to a
// stack overflow, at which point the partially parsed arrow
// function concise body happens to be a valid expression. This
// is a problem only for arrow functions with single statement
// bodies, since there is no end token suck as "}" for normal
// functions.
if (scanner()->location().end_pos == shared_info->end_position()) {
// The pre-parser saw an arrow function here, so the full parser
// must produce a FunctionLiteral.
DCHECK(expression->IsFunctionLiteral());
result = expression->AsFunctionLiteral();
} else {
result = NULL;
ok = false;
}
}
} else if (shared_info->is_default_constructor()) {
result = DefaultConstructor(IsSubclassConstructor(shared_info->kind()),
scope, shared_info->start_position(),
......
// 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: --harmony-arrow-functions
// This used to trigger a segfault because of NULL being accessed.
function f() {
var a = [10];
try {
f();
} catch(e) {
a.map((v) => v + 1);
}
}
f();
// 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: --harmony-arrow-functions
// This used to trigger crash because of an unhandled stack overflow.
function f() {
var a = [10];
try {
f();
} catch(e) {
a.map(v => v + 1);
}
}
f();
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