Skip to content

Commit

Permalink
Don't allow catch to bind to eval or arguments in strict mode
Browse files Browse the repository at this point in the history
Summary:
Implement a point in [section C](https://tc39.es/ecma262/multipage/strict-mode-of-ecmascript.html#sec-strict-mode-of-ecmascript) of the spec.

> It is a SyntaxError if a CatchParameter occurs within strict mode code and BoundNames of CatchParameter contains either `eval` or `arguments`

Perform this check in the `SemanticValidator`.

Reviewed By: jpporto

Differential Revision: D41864654

fbshipit-source-id: 0aaf981965c02a347052fe43047fa0dd4630b9b0
  • Loading branch information
fbmal7 authored and facebook-github-bot committed Mar 29, 2023
1 parent f6b56d3 commit 838d1e4
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
27 changes: 27 additions & 0 deletions lib/AST/SemanticValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,34 @@ void SemanticValidator::visit(RegExpLiteralNode *regexp) {
visitESTreeChildren(*this, regexp);
}

void SemanticValidator::validateCatchClause(const Node *catchClause) {
// The catch clause is optional, so bail early if it doesn't exist.
if (!catchClause) {
return;
}
auto *castedCatch = llvh::dyn_cast<ESTree::CatchClauseNode>(catchClause);
if (!castedCatch) {
return;
}
// Bail early if there is no identifier in the parameter of the catch.
if (!castedCatch->_param ||
!llvh::isa<ESTree::IdentifierNode>(castedCatch->_param)) {
return;
}
auto *idNode = cast<ESTree::IdentifierNode>(castedCatch->_param);
if (!isValidDeclarationName(idNode)) {
sm_.error(
idNode->getSourceRange(),
"cannot bind to " + idNode->_name->str() +
" in the catch clause in strict mode");
}
}

void SemanticValidator::visit(TryStatementNode *tryStatement) {
if (curFunction()->strictMode) {
validateCatchClause(tryStatement->_handler);
}
// The catch parameter cannot bind to 'eval' or 'arguments' in strict mode.
// A try statement with both catch and finally handlers is technically
// two nested try statements. Transform:
//
Expand Down
4 changes: 4 additions & 0 deletions lib/AST/SemanticValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ class SemanticValidator {
FunctionInfo::BlockDecls *varIdents,
FunctionInfo::BlockDecls *scopedIdents);

/// Ensure that the catch clause of a try statement does not bind any
/// identifiers to 'eval' or 'arguments'. Should only be used in strict mode.
void validateCatchClause(const Node *catchClause);

/// Ensure that the specified node is a valid target for an assignment, in
/// other words it is an l-value, a Pattern (checked recursively) or an Empty
/// (used by elision).
Expand Down
25 changes: 25 additions & 0 deletions test/hermes/catch_invalid_bindings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

// RUN: %hermes %s | %FileCheck --match-full-lines %s
'use strict';

print("catch");
//CHECK-LABEL: catch

try {
eval('try{}catch(eval){}')
} catch (err){
print(err instanceof SyntaxError);
}
//CHECK-NEXT: true
try {
eval('try{}catch(arguments){}')
} catch (err){
print(err instanceof SyntaxError);
}
//CHECK-NEXT: true

0 comments on commit 838d1e4

Please sign in to comment.