Commit 2d408562 authored by littledan's avatar littledan Committed by Commit bot

Ensure scopes are backed by blocks in the body of for loops

Clusterfuzz testing discovered that sloppy-mode block-scoped function
declarations introduce lexically-scoped variables in scopes that were
thrown away under the expectation that no lexically-scoped variables
were introduced. These cases are:

  for (;;) function foo() {}
  for (x in y) function foo() {}

This patch ensures that a block is created in those cases to hold the
lexically scoped variable. Usually, scope analysis should discover that
that block is not important, and it should not have a runtime
representation.

BUG=chromium:536750,chromium:536751
LOG=Y
R=adamk

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

Cr-Commit-Position: refs/heads/master@{#31109}
parent 12d28873
......@@ -3786,12 +3786,19 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
Expression* enumerable = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
// Make a block around the statement in case a lexical binding
// is introduced, e.g. by a FunctionDeclaration.
Block* block =
factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
Statement* body = ParseSubStatement(NULL, CHECK_OK);
InitializeForEachStatement(loop, expression, enumerable, body);
block->statements()->Add(body, zone());
InitializeForEachStatement(loop, expression, enumerable, block);
scope_ = saved_scope;
for_scope->set_end_position(scanner()->location().end_pos);
for_scope = for_scope->FinalizeBlockScope();
DCHECK(for_scope == NULL);
if (for_scope != nullptr) {
block->set_scope(for_scope);
}
// Parsed for-in loop.
return loop;
......@@ -3861,10 +3868,20 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
// const x = i;
// for (; c; n) b
// }
DCHECK(init != NULL);
//
// or, desugar
// for (; c; n) b
// into
// {
// for (; c; n) b
// }
// just in case b introduces a lexical binding some other way, e.g., if b
// is a FunctionDeclaration.
Block* block =
factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
block->statements()->Add(init, zone());
if (init != nullptr) {
block->statements()->Add(init, zone());
}
block->statements()->Add(loop, zone());
block->set_scope(for_scope);
loop->Initialize(NULL, cond, next, body);
......
// 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-sloppy --harmony-sloppy-function --harmony-sloppy-let
// At some point, this code led to DCHECK errors in debug mode
for (; false;) function foo() {};
for (x in []) function foo() {};
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