From 4b0aa9942c9f98262c4437de31633f37005779fa Mon Sep 17 00:00:00 2001 From: Istvan Romai Date: Wed, 25 Jun 2025 15:35:11 +0200 Subject: [PATCH] Fix method assignment crash Modified the ETS Analyzer to recognize invalid method assignments and throw error instead of crashing Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICHTZ0 Internal issue: #26792 Change-Id: Ida8bfa8493ee5e70ff28254b22306c4ea76c5af8 Signed-off-by: Istvan Romai --- ets2panda/checker/ETSAnalyzer.cpp | 29 +++++++++- .../ast/compiler/ets/identifierReference9.ets | 2 +- .../ast/compiler/ets/method-assignment.ets | 56 +++++++++++++++++++ ets2panda/util/diagnostic/semantic.yaml | 8 ++- 4 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/method-assignment.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index a9d88755dd..71bda723e4 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -1150,6 +1150,33 @@ checker::Type *ETSAnalyzer::GetSmartType(ir::AssignmentExpression *expr, checker return smartType; } +static bool IsMethodDefinition(const ir::Expression *const expression) +{ + return expression->IsMemberExpression() && expression->AsMemberExpression()->Property() != nullptr && + expression->AsMemberExpression()->Property()->Variable() != nullptr && + expression->AsMemberExpression()->Property()->Variable()->Declaration() != nullptr && + expression->AsMemberExpression()->Property()->Variable()->Declaration()->Node()->IsMethodDefinition(); +} + +static bool IsInvalidMethodAssignment(const ir::AssignmentExpression *const expr, ETSChecker *checker) +{ + auto left = expr->Left(); + if (IsMethodDefinition(left)) { + { + auto methodDefinition = + left->AsMemberExpression()->Property()->Variable()->Declaration()->Node()->AsMethodDefinition(); + if (!methodDefinition->IsSetter() && + std::none_of(methodDefinition->Overloads().cbegin(), methodDefinition->Overloads().cend(), + [](const auto *overload) { return overload->IsSetter(); })) { + checker->LogError(diagnostic::METHOD_ASSIGNMENT, expr->Left()->Start()); + return true; + } + } + } + + return false; +} + checker::Type *ETSAnalyzer::Check(ir::AssignmentExpression *const expr) const { if (expr->TsType() != nullptr) { @@ -1164,7 +1191,7 @@ checker::Type *ETSAnalyzer::Check(ir::AssignmentExpression *const expr) const const auto leftType = expr->Left()->Check(checker); - if (IsInvalidArrayMemberAssignment(expr, checker)) { + if (IsInvalidArrayMemberAssignment(expr, checker) || IsInvalidMethodAssignment(expr, checker)) { expr->SetTsType(checker->GlobalTypeError()); return expr->TsType(); } diff --git a/ets2panda/test/ast/compiler/ets/identifierReference9.ets b/ets2panda/test/ast/compiler/ets/identifierReference9.ets index 006fc0197d..3021ebf7a1 100644 --- a/ets2panda/test/ast/compiler/ets/identifierReference9.ets +++ b/ets2panda/test/ast/compiler/ets/identifierReference9.ets @@ -25,4 +25,4 @@ class A { } } -/* @@? 24:16 Error TypeError: Type 'Int' cannot be assigned to type '() => void' */ +/* @@? 24:5 Error TypeError: Class methods cannot be overwritten. */ diff --git a/ets2panda/test/ast/compiler/ets/method-assignment.ets b/ets2panda/test/ast/compiler/ets/method-assignment.ets new file mode 100644 index 0000000000..8bf46b3b8d --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/method-assignment.ets @@ -0,0 +1,56 @@ +/* + * 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 Base { + baseFoo() {} + static staticBaseFoo() {} +} + +interface I { + interfaceFoo() {} +} + +class C extends Base implements I { + foo1() {} + static foo2() {} + + constructor() + { + this.interfaceFoo = bar; + } + + constructor(arg: () => void) + { + this.foo1 = arg; + } +} + +function bar() {} + +let c = new C(); +c = new C(bar); +c.baseFoo = bar; +C.staticBaseFoo = bar; +c.foo1 = bar; +C.foo2 = bar; +c.interfaceFoo = bar; + +/* @@? 31:9 Error TypeError: Class methods cannot be overwritten. */ +/* @@? 36:9 Error TypeError: Class methods cannot be overwritten. */ +/* @@? 44:1 Error TypeError: Class methods cannot be overwritten. */ +/* @@? 45:1 Error TypeError: Class methods cannot be overwritten. */ +/* @@? 46:1 Error TypeError: Class methods cannot be overwritten. */ +/* @@? 47:1 Error TypeError: Class methods cannot be overwritten. */ +/* @@? 48:1 Error TypeError: Class methods cannot be overwritten. */ diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index db1355f996..96a7f4cbef 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -1557,5 +1557,9 @@ semantic: message: "overload declaration cannot contain abstract methods." - name: INVALID_RECORD_PROPERTY - id: 383 - message: "Invalid record property" \ No newline at end of file + id: 393 + message: "Invalid record property" + +- name: METHOD_ASSIGNMENT + id: 394 + message: "Class methods cannot be overwritten." -- Gitee