From 0360a730cab123d92251520071fc5846ea0c1e54 Mon Sep 17 00:00:00 2001 From: xingshunxiang Date: Mon, 23 Jun 2025 15:29:46 +0800 Subject: [PATCH] Fix several bugs from fuzzing case Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICHJSW?from=project-issue Description: some crash bugs from fuzzer Reason: 1. in case1, {@@} will invoke the ETSFormattedParse, if the insertNode is empty, it will return BrokenType and Throw logError, BrokenType will cause nullptr segV in EnumCheck, since it have no tsType, so subsitute it with BrokenExpression, it will has typeError as tsType. 2. in case2, some poccessing of boolean had been lost, now add it. 3. in case3, parser goes into TypedParser and return an unsupported astnode, so override the related function to return the correct astnode 4. in case4, invalid namespace inside blockstatement cannot be transfered to classDefinition, so cause SegV in the later lowering Tests: ninja tests passed tests/tests-u-runner/runner.sh --ets-cts --show-progress --build-dir x64.release --processes=all passed tests/tests-u-runner/runner.sh --ets-func-tests --show-progress --build-dir x64.release --processes=all passed tests/tests-u-runner/runner.sh --astchecker --show-progress --build-dir x64.release --processes=all passed tests/tests-u-runner/runner.sh --ets-runtime --show-progress --build-dir x64.release --processes=all passed tests/tests-u-runner/runner.sh --parser --no-js --show-progress --build-dir x64.release --processes=all passed Signed-off-by: xingshunxiang --- .../ets/constantExpressionLowering.cpp | 3 +++ .../ets/topLevelStmts/globalClassHandler.cpp | 17 ++++++------ .../ets/topLevelStmts/globalClassHandler.h | 2 +- ets2panda/parser/ETSFormattedParser.cpp | 2 +- ets2panda/parser/ETSparser.h | 2 +- ets2panda/parser/ETSparserNamespaces.cpp | 6 ++--- ets2panda/parser/TypedParser.cpp | 7 ++++- ets2panda/parser/TypedParser.h | 1 + .../ast/compiler/ets/binary_operator_neg.ets | 21 +++++++++++++++ .../compiler/ets/classproperty_init_neg.ets | 18 +++++++++++++ .../compiler/ets/invalid_namespace_neg.ets | 27 +++++++++++++++++++ .../compiler/ets/invalid_namespace_neg2.ets | 22 +++++++++++++++ 12 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/binary_operator_neg.ets create mode 100644 ets2panda/test/ast/compiler/ets/classproperty_init_neg.ets create mode 100644 ets2panda/test/ast/compiler/ets/invalid_namespace_neg.ets create mode 100644 ets2panda/test/ast/compiler/ets/invalid_namespace_neg2.ets diff --git a/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp b/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp index 57b3ae2698..a33932a5ba 100644 --- a/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp @@ -312,6 +312,9 @@ static ir::AstNode *CastNumberOrCharLiteralFrom(const ir::Literal *lit, ir::Prim public_lib::Context *context) { switch (type) { + case ir::PrimitiveType::BOOLEAN: + // Note: we do nothing for `class A {b5 : boolean = 7;}` here, type error will be thrown in checker. + return const_cast(lit); case ir::PrimitiveType::CHAR: return CastNumberOrCharLiteralFromTo(lit, context); case ir::PrimitiveType::BYTE: diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp index 1aaced464c..2f41123fae 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp @@ -184,18 +184,18 @@ ArenaVector GlobalClassHandler::TransformNamespaces(ArenaVector return classDecls; } -void GlobalClassHandler::TransformBrokenNamespace() +void GlobalClassHandler::TransformBrokenNamespace(ir::AstNode *node) { - globalProgram_->Ast()->TransformChildrenRecursively( + node->TransformChildrenRecursively( // clang-format off // CC-OFFNXT(G.FMT.14-CPP) project code style - [this](ir::AstNode *node) -> ir::AstNode* { - if (node->IsETSModule() && node->AsETSModule()->IsNamespace()) { - auto res = TransformNamespace(node->AsETSModule()); - res->SetParent(node->Parent()); + [this](ir::AstNode *child) -> ir::AstNode* { + if (child->IsETSModule() && child->AsETSModule()->IsNamespace()) { + auto res = TransformNamespace(child->AsETSModule()); + res->SetParent(child->Parent()); return res; } - return node; + return child; }, // clang-format on "TransformBrokenNamespace"); @@ -321,7 +321,7 @@ void GlobalClassHandler::SetupGlobalClass(const ArenaVector & globalClass->SetGlobalInitialized(); CollectProgramGlobalClasses(namespaces); - TransformBrokenNamespace(); + TransformBrokenNamespace(globalProgram_->Ast()); auto initializerBlockStmts = FormInitStaticBlockMethodStatements(moduleDependencies, std::move(initializerBlock)); CollectExportedClasses(globalClass, globalProgram_->Ast()->Statements()); @@ -434,6 +434,7 @@ ArenaVector GlobalClassHandler::FormInitMethodStatements(const statements.insert(statements.end(), ps.begin(), ps.end()); } for (auto st : statements) { + TransformBrokenNamespace(st); st->SetParent(nullptr); } return statements; diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h index 0a861be7a7..2b9027158a 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h @@ -82,7 +82,7 @@ private: ArenaVector> FormInitStaticBlockMethodStatements( const ModuleDependencies *moduleDependencies, ArenaVector &&initStatements); - void TransformBrokenNamespace(); + void TransformBrokenNamespace(ir::AstNode *node); ArenaVector FormInitMethodStatements(const ModuleDependencies *moduleDependencies, ArenaVector &&initStatements); diff --git a/ets2panda/parser/ETSFormattedParser.cpp b/ets2panda/parser/ETSFormattedParser.cpp index d0b01fdad5..f5bb28b326 100644 --- a/ets2panda/parser/ETSFormattedParser.cpp +++ b/ets2panda/parser/ETSFormattedParser.cpp @@ -71,7 +71,7 @@ ir::Expression *ETSParser::ParseExpressionFormatPlaceholder() LogUnexpectedToken(lexer::TokenType::PUNCTUATOR_FORMAT); const auto &rangeToken = Lexer()->GetToken().Loc(); Lexer()->NextToken(); - return AllocBrokenType(rangeToken); + return AllocBrokenExpression(rangeToken); } ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType(); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 94f513f1db..aa60762d9a 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -396,7 +396,7 @@ private: ir::ModifierFlags flags = ir::ModifierFlags::NONE) override; bool CheckInNamespaceContextIsExported(); ir::ETSModule *ParseNamespaceStatement(ir::ModifierFlags memberModifiers); - ir::ETSModule *ParseNamespace(ir::ModifierFlags flags); + ir::Statement *ParseNamespace(ir::ModifierFlags flags) override; ir::ETSModule *ParseNamespaceImp(ir::ModifierFlags flags); using NamespaceBody = std::tuple, lexer::SourceRange>; NamespaceBody ParseNamespaceBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags); diff --git a/ets2panda/parser/ETSparserNamespaces.cpp b/ets2panda/parser/ETSparserNamespaces.cpp index 5024059997..72c121d5fc 100644 --- a/ets2panda/parser/ETSparserNamespaces.cpp +++ b/ets2panda/parser/ETSparserNamespaces.cpp @@ -41,7 +41,7 @@ ir::ETSModule *ETSParser::ParseNamespaceStatement(ir::ModifierFlags memberModifi GetContext().Status() |= ParserStatus::IN_NAMESPACE; IncrementNamespaceNestedRank(); - ir::ETSModule *result = ParseNamespace(modifiers); + auto *result = ParseNamespace(modifiers); DecrementNamespaceNestedRank(); if (GetNamespaceNestedRank() == 0) { @@ -50,10 +50,10 @@ ir::ETSModule *ETSParser::ParseNamespaceStatement(ir::ModifierFlags memberModifi if ((memberModifiers & ir::ModifierFlags::DECLARE) != 0) { GetContext().Status() &= ~ParserStatus::IN_AMBIENT_CONTEXT; } - return result; + return result->AsETSModule(); } -ir::ETSModule *ETSParser::ParseNamespace(ir::ModifierFlags flags) +ir::Statement *ETSParser::ParseNamespace(ir::ModifierFlags flags) { if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) == 0) { LogError(diagnostic::NAMESPACE_ONLY_TOP_OR_IN_NAMESPACE); diff --git a/ets2panda/parser/TypedParser.cpp b/ets2panda/parser/TypedParser.cpp index 02dd76cabd..c47a3e4c7a 100644 --- a/ets2panda/parser/TypedParser.cpp +++ b/ets2panda/parser/TypedParser.cpp @@ -170,7 +170,7 @@ ir::Statement *TypedParser::ParsePotentialExpressionStatement(StatementParsingFl } case lexer::TokenType::KEYW_NAMESPACE: { if (((GetContext().Status() & ParserStatus::IN_AMBIENT_CONTEXT) != 0U) || IsNamespaceDecl()) { - return ParseModuleDeclaration(); + return ParseNamespace(ir::ModifierFlags::NONE); } [[fallthrough]]; } @@ -225,6 +225,11 @@ ir::Statement *TypedParser::ParseModuleDeclaration([[maybe_unused]] StatementPar return ParseModuleOrNamespaceDeclaration(startLoc); } +ir::Statement *TypedParser::ParseNamespace([[maybe_unused]] ir::ModifierFlags flags) +{ + return ParseModuleDeclaration(); +} + ir::ArrowFunctionExpression *TypedParser::ParseGenericArrowFunction(bool isThrowError) { ArrowFunctionContext arrowFunctionContext(this, false); diff --git a/ets2panda/parser/TypedParser.h b/ets2panda/parser/TypedParser.h index 226f8052e6..ec50263d42 100644 --- a/ets2panda/parser/TypedParser.h +++ b/ets2panda/parser/TypedParser.h @@ -87,6 +87,7 @@ protected: // NOLINTNEXTLINE(google-default-arguments) ir::Statement *ParseModuleDeclaration(StatementParsingFlags flags = StatementParsingFlags::NONE) override; + virtual ir::Statement *ParseNamespace(ir::ModifierFlags flags); virtual void CheckIfTypeParameterNameIsReserved() {}; virtual ArenaVector ParseInterfaceExtendsClause(); virtual ir::Statement *ParseDeclareAndDecorators(StatementParsingFlags flags); diff --git a/ets2panda/test/ast/compiler/ets/binary_operator_neg.ets b/ets2panda/test/ast/compiler/ets/binary_operator_neg.ets new file mode 100644 index 0000000000..8b71c849f8 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/binary_operator_neg.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 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. + */ + +/* @@ label1 */@@/@ + +/* @@@ label1 Error SyntaxError: Unexpected token '@@'. */ +/* @@? 21:93 Error SyntaxError: Identifier expected, got 'end of stream'. */ +/* @@? 21:93 Error SyntaxError: Unexpected token 'end of stream'. */ +/* @@? 21:93 Error SyntaxError: Annotations are not allowed on this type of declaration. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/classproperty_init_neg.ets b/ets2panda/test/ast/compiler/ets/classproperty_init_neg.ets new file mode 100644 index 0000000000..4f419d33d4 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/classproperty_init_neg.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +class A {b5 : boolean = /* @@ label1 */7;} + +/* @@@ label1 Error TypeError: Type 'Int' cannot be assigned to type 'Boolean' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/invalid_namespace_neg.ets b/ets2panda/test/ast/compiler/ets/invalid_namespace_neg.ets new file mode 100644 index 0000000000..2f3707f2ac --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/invalid_namespace_neg.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 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. + */ + +namespace C{ + { + let y: number = + /* @@ label1 */} + + namespace C { + let xsx = 1 + } +} + +/* @@@ label1 Error SyntaxError: Unexpected token '}'. */ +/* @@? 28:1 Error SyntaxError: Unexpected token. */ diff --git a/ets2panda/test/ast/compiler/ets/invalid_namespace_neg2.ets b/ets2panda/test/ast/compiler/ets/invalid_namespace_neg2.ets new file mode 100644 index 0000000000..c7941e4248 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/invalid_namespace_neg2.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 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. + */ + +{ + /* @@ label1 */namespace C { + let my:number = 1 + } +} + +/* @@@ label1 Error SyntaxError: Namespace is allowed only at the top level or inside a namespace. */ -- Gitee