From dc9b063e6c7fc6e74ed58e12c6280dba46bc65af Mon Sep 17 00:00:00 2001 From: huyunhui Date: Thu, 25 Jan 2024 02:50:13 +0000 Subject: [PATCH] fix dereference of nullptr Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8YMMD Signed-off-by: huyunhui Change-Id: I9e4d5455bba6c63796190d8137dba4909b2ef2ee --- es2panda/parser/expressionParser.cpp | 104 +++++++++++------- es2panda/parser/parserImpl.h | 1 + .../optional-chain-syntax-error-expected.txt | 1 + .../optional-chain-syntax-error.js | 16 +++ es2panda/test/runner.py | 1 + 5 files changed, 85 insertions(+), 38 deletions(-) create mode 100644 es2panda/test/parser/js/language/expressions/optional-chain/optional-chain-syntax-error-expected.txt create mode 100644 es2panda/test/parser/js/language/expressions/optional-chain/optional-chain-syntax-error.js diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index 69ec9a6124..e61e4fa066 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -1369,58 +1369,86 @@ ir::Expression *ParserImpl::ParseOptionalChain(ir::Expression *leftSideExpr) lexer::TokenType tokenType = lexer_->GetToken().Type(); ir::Expression *returnExpression = nullptr; - if (tokenType == lexer::TokenType::PUNCTUATOR_HASH_MARK) { - auto *privateIdent = ParsePrivateIdentifier(); - returnExpression = AllocNode( - leftSideExpr, privateIdent, ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, true); - returnExpression->SetRange({leftSideExpr->Start(), privateIdent->End()}); - lexer_->NextToken(); - } - - if (tokenType == lexer::TokenType::LITERAL_IDENT) { - auto *identNode = AllocNode(lexer_->GetToken().Ident()); - identNode->SetReference(); - identNode->SetRange(lexer_->GetToken().Loc()); + switch (tokenType) { + case lexer::TokenType::PUNCTUATOR_HASH_MARK: + case lexer::TokenType::LITERAL_IDENT: + case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { + returnExpression = ParseOptionalMemberExpression(leftSideExpr); + break; + } + case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: { + returnExpression = ParseCallExpression(leftSideExpr, true); + break; + } + case lexer::TokenType::PUNCTUATOR_LESS_THAN: { + if (Extension() != ScriptExtension::TS) { + ThrowSyntaxError("Unexpected token"); + } - returnExpression = AllocNode( - leftSideExpr, identNode, ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, true); - returnExpression->SetRange({leftSideExpr->Start(), identNode->End()}); - lexer_->NextToken(); - } + ir::TSTypeParameterInstantiation *typeParams = ParseTsTypeParameterInstantiation(true); - if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { - lexer_->NextToken(); // eat '[' - ir::Expression *propertyNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); + if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { + ThrowSyntaxError("Expected '('"); + } - if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) { + returnExpression = ParseCallExpression(leftSideExpr, true); + returnExpression->AsCallExpression()->SetTypeParams(typeParams); + break; + } + case lexer::TokenType::PUNCTUATOR_BACK_TICK: { + ThrowSyntaxError("Tagged Template Literals are not allowed in optionalChain"); + } + default: { ThrowSyntaxError("Unexpected token"); } - - returnExpression = AllocNode( - leftSideExpr, propertyNode, ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS, true, true); - returnExpression->SetRange({leftSideExpr->Start(), lexer_->GetToken().End()}); - lexer_->NextToken(); - } - - if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { - returnExpression = ParseCallExpression(leftSideExpr, true); - } - - if (Extension() == ScriptExtension::TS && tokenType == lexer::TokenType::PUNCTUATOR_LESS_THAN) { - ir::TSTypeParameterInstantiation *typeParams = ParseTsTypeParameterInstantiation(true); - returnExpression = ParseCallExpression(leftSideExpr, true); - returnExpression->AsCallExpression()->SetTypeParams(typeParams); } // Static semantic - if (tokenType == lexer::TokenType::PUNCTUATOR_BACK_TICK || - lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK) { + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK) { ThrowSyntaxError("Tagged Template Literals are not allowed in optionalChain"); } return returnExpression; } +ir::Expression *ParserImpl::ParseOptionalMemberExpression(ir::Expression *object) +{ + ir::Expression *property = nullptr; + bool computed = false; + auto kind = ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS; + + lexer::SourcePosition end; + lexer::TokenType tokenType = lexer_->GetToken().Type(); + ASSERT(tokenType == lexer::TokenType::PUNCTUATOR_HASH_MARK || tokenType == lexer::TokenType::LITERAL_IDENT || + tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET); + + if (tokenType == lexer::TokenType::PUNCTUATOR_HASH_MARK) { + property = ParsePrivateIdentifier(); + end = property->End(); + } else if (tokenType == lexer::TokenType::LITERAL_IDENT) { + property = AllocNode(lexer_->GetToken().Ident()); + property->AsIdentifier()->SetReference(); + property->SetRange(lexer_->GetToken().Loc()); + end = lexer_->GetToken().End(); + lexer_->NextToken(); + } else { + computed = true; + kind = ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS; + lexer_->NextToken(); // eat '[' + property = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); + + if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) { + ThrowSyntaxError("Expected ']'"); + } + end = lexer_->GetToken().End(); + lexer_->NextToken(); + } + + auto *memberExpr = AllocNode(object, property, kind, computed, true); + memberExpr->SetRange({object->Start(), end}); + return memberExpr; +} + ir::ArrowFunctionExpression *ParserImpl::ParsePotentialArrowExpression(ir::Expression **returnExpression, const lexer::SourcePosition &startLoc, bool ignoreCallExpression) diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 510d471bf5..d52362cb44 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -439,6 +439,7 @@ private: ir::AssertEntry *ParseAssertEntry(); ir::FunctionExpression *ParseFunctionExpression(ParserStatus newStatus = ParserStatus::NO_OPTS); ir::Expression *ParseOptionalChain(ir::Expression *leftSideExpr); + ir::Expression *ParseOptionalMemberExpression(ir::Expression *object); void ParseNameSpaceImport(ArenaVector *specifiers, bool isType); ir::Identifier *ParseNamedImport(const lexer::Token &importedToken); binder::Decl *AddImportDecl(bool isType, diff --git a/es2panda/test/parser/js/language/expressions/optional-chain/optional-chain-syntax-error-expected.txt b/es2panda/test/parser/js/language/expressions/optional-chain/optional-chain-syntax-error-expected.txt new file mode 100644 index 0000000000..e913fba9e7 --- /dev/null +++ b/es2panda/test/parser/js/language/expressions/optional-chain/optional-chain-syntax-error-expected.txt @@ -0,0 +1 @@ +SyntaxError: Unexpected token [optional-chain-syntax-error.js:16:4] diff --git a/es2panda/test/parser/js/language/expressions/optional-chain/optional-chain-syntax-error.js b/es2panda/test/parser/js/language/expressions/optional-chain/optional-chain-syntax-error.js new file mode 100644 index 0000000000..c93daf265a --- /dev/null +++ b/es2panda/test/parser/js/language/expressions/optional-chain/optional-chain-syntax-error.js @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +x?.?.y \ No newline at end of file diff --git a/es2panda/test/runner.py b/es2panda/test/runner.py index ded4177d45..81c2a64419 100755 --- a/es2panda/test/runner.py +++ b/es2panda/test/runner.py @@ -1521,6 +1521,7 @@ def main(): runner.add_directory("parser/js/emptySource", "js", ["--dump-assembly"]) runner.add_directory("parser/js/language/arguments-object", "js", ["--parse-only"]) runner.add_directory("parser/js/language/statements/for-statement", "js", ["--parse-only", "--dump-ast"]) + runner.add_directory("parser/js/language/expressions/optional-chain", "js", ["--parse-only", "--dump-ast"]) runner.add_directory("parser/sendable_class", "ts", ["--dump-assembly", "--dump-literal-buffer", "--module"]) runners.append(runner) -- Gitee