arkanalyzer 1.0.20 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Config.d.ts +70 -70
- package/lib/Config.js +198 -198
- package/lib/Scene.d.ts +316 -316
- package/lib/Scene.js +1316 -1316
- package/lib/callgraph/algorithm/AbstractAnalysis.d.ts +28 -28
- package/lib/callgraph/algorithm/AbstractAnalysis.js +144 -144
- package/lib/callgraph/algorithm/ClassHierarchyAnalysis.d.ts +10 -10
- package/lib/callgraph/algorithm/ClassHierarchyAnalysis.js +69 -69
- package/lib/callgraph/algorithm/RapidTypeAnalysis.d.ts +15 -15
- package/lib/callgraph/algorithm/RapidTypeAnalysis.js +146 -146
- package/lib/callgraph/common/Statistics.d.ts +57 -57
- package/lib/callgraph/common/Statistics.js +228 -228
- package/lib/callgraph/model/CallGraph.d.ts +96 -96
- package/lib/callgraph/model/CallGraph.js +354 -354
- package/lib/callgraph/model/builder/CallGraphBuilder.d.ts +15 -15
- package/lib/callgraph/model/builder/CallGraphBuilder.js +106 -106
- package/lib/callgraph/pointerAnalysis/Context.d.ts +37 -37
- package/lib/callgraph/pointerAnalysis/Context.js +155 -155
- package/lib/callgraph/pointerAnalysis/DummyCallCreator.d.ts +22 -22
- package/lib/callgraph/pointerAnalysis/DummyCallCreator.js +104 -104
- package/lib/callgraph/pointerAnalysis/PTAUtils.d.ts +5 -5
- package/lib/callgraph/pointerAnalysis/PTAUtils.js +46 -46
- package/lib/callgraph/pointerAnalysis/Pag.d.ts +261 -261
- package/lib/callgraph/pointerAnalysis/Pag.js +930 -930
- package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts +157 -157
- package/lib/callgraph/pointerAnalysis/PagBuilder.js +1399 -1399
- package/lib/callgraph/pointerAnalysis/PointerAnalysis.d.ts +72 -72
- package/lib/callgraph/pointerAnalysis/PointerAnalysis.js +573 -573
- package/lib/callgraph/pointerAnalysis/PointerAnalysisConfig.d.ts +15 -15
- package/lib/callgraph/pointerAnalysis/PointerAnalysisConfig.js +81 -81
- package/lib/callgraph/pointerAnalysis/PtsDS.d.ts +80 -80
- package/lib/callgraph/pointerAnalysis/PtsDS.js +308 -308
- package/lib/core/base/Constant.d.ts +48 -48
- package/lib/core/base/Constant.js +103 -103
- package/lib/core/base/Decorator.d.ts +15 -15
- package/lib/core/base/Decorator.js +46 -46
- package/lib/core/base/DefUseChain.d.ts +8 -8
- package/lib/core/base/DefUseChain.js +25 -25
- package/lib/core/base/Expr.d.ts +340 -340
- package/lib/core/base/Expr.js +917 -917
- package/lib/core/base/Local.d.ts +104 -104
- package/lib/core/base/Local.js +176 -176
- package/lib/core/base/Position.d.ts +30 -30
- package/lib/core/base/Position.js +147 -147
- package/lib/core/base/Ref.d.ts +173 -173
- package/lib/core/base/Ref.js +374 -374
- package/lib/core/base/Stmt.d.ts +237 -237
- package/lib/core/base/Stmt.js +525 -525
- package/lib/core/base/Trap.d.ts +8 -8
- package/lib/core/base/Trap.js +30 -30
- package/lib/core/base/Type.d.ts +308 -308
- package/lib/core/base/Type.js +639 -639
- package/lib/core/base/TypeExpr.d.ts +71 -71
- package/lib/core/base/TypeExpr.js +155 -155
- package/lib/core/base/Value.d.ts +32 -32
- package/lib/core/base/Value.js +16 -16
- package/lib/core/common/ArkError.d.ts +14 -14
- package/lib/core/common/ArkError.js +28 -28
- package/lib/core/common/ArkIRTransformer.d.ts +67 -67
- package/lib/core/common/ArkIRTransformer.js +690 -690
- package/lib/core/common/ArkValueTransformer.d.ts +89 -89
- package/lib/core/common/ArkValueTransformer.js +1478 -1478
- package/lib/core/common/Builtin.d.ts +36 -36
- package/lib/core/common/Builtin.js +81 -81
- package/lib/core/common/Const.d.ts +21 -21
- package/lib/core/common/Const.js +43 -43
- package/lib/core/common/DummyMainCreater.d.ts +46 -46
- package/lib/core/common/DummyMainCreater.js +319 -319
- package/lib/core/common/EtsConst.d.ts +73 -73
- package/lib/core/common/EtsConst.js +1021 -1021
- package/lib/core/common/ExprUseReplacer.d.ts +21 -21
- package/lib/core/common/ExprUseReplacer.js +124 -124
- package/lib/core/common/IRInference.d.ts +36 -36
- package/lib/core/common/IRInference.d.ts.map +1 -1
- package/lib/core/common/IRInference.js +651 -648
- package/lib/core/common/IRUtils.d.ts +18 -18
- package/lib/core/common/IRUtils.js +141 -141
- package/lib/core/common/ModelUtils.d.ts +70 -70
- package/lib/core/common/ModelUtils.js +712 -712
- package/lib/core/common/RefUseReplacer.d.ts +13 -13
- package/lib/core/common/RefUseReplacer.js +52 -52
- package/lib/core/common/SdkUtils.d.ts +8 -8
- package/lib/core/common/SdkUtils.js +105 -105
- package/lib/core/common/StmtDefReplacer.d.ts +12 -12
- package/lib/core/common/StmtDefReplacer.js +41 -41
- package/lib/core/common/StmtUseReplacer.d.ts +16 -16
- package/lib/core/common/StmtUseReplacer.js +108 -108
- package/lib/core/common/TSConst.d.ts +18 -18
- package/lib/core/common/TSConst.js +36 -36
- package/lib/core/common/TypeInference.d.ts +102 -102
- package/lib/core/common/TypeInference.js +748 -748
- package/lib/core/common/ValueUtil.d.ts +12 -12
- package/lib/core/common/ValueUtil.js +54 -54
- package/lib/core/common/VisibleValue.d.ts +36 -36
- package/lib/core/common/VisibleValue.js +212 -212
- package/lib/core/dataflow/DataflowProblem.d.ts +20 -20
- package/lib/core/dataflow/DataflowProblem.js +20 -20
- package/lib/core/dataflow/DataflowResult.d.ts +7 -7
- package/lib/core/dataflow/DataflowResult.js +26 -26
- package/lib/core/dataflow/DataflowSolver.d.ts +43 -43
- package/lib/core/dataflow/DataflowSolver.js +307 -307
- package/lib/core/dataflow/Edge.d.ts +11 -11
- package/lib/core/dataflow/Edge.js +31 -31
- package/lib/core/dataflow/Fact.d.ts +6 -6
- package/lib/core/dataflow/Fact.js +24 -24
- package/lib/core/dataflow/GenericDataFlow.d.ts +142 -142
- package/lib/core/dataflow/GenericDataFlow.js +109 -109
- package/lib/core/dataflow/ReachingDef.d.ts +62 -62
- package/lib/core/dataflow/ReachingDef.js +168 -168
- package/lib/core/dataflow/UndefinedVariable.d.ts +45 -45
- package/lib/core/dataflow/UndefinedVariable.js +288 -288
- package/lib/core/dataflow/Util.d.ts +9 -9
- package/lib/core/dataflow/Util.js +64 -64
- package/lib/core/graph/BaseExplicitGraph.d.ts +58 -58
- package/lib/core/graph/BaseExplicitGraph.js +157 -157
- package/lib/core/graph/BaseImplicitGraph.d.ts +77 -77
- package/lib/core/graph/BaseImplicitGraph.js +78 -78
- package/lib/core/graph/BasicBlock.d.ts +104 -104
- package/lib/core/graph/BasicBlock.js +280 -280
- package/lib/core/graph/Cfg.d.ts +59 -59
- package/lib/core/graph/Cfg.js +282 -282
- package/lib/core/graph/DependsGraph.d.ts +35 -35
- package/lib/core/graph/DependsGraph.js +87 -87
- package/lib/core/graph/DominanceFinder.d.ts +15 -15
- package/lib/core/graph/DominanceFinder.js +121 -121
- package/lib/core/graph/DominanceTree.d.ts +12 -12
- package/lib/core/graph/DominanceTree.js +70 -70
- package/lib/core/graph/GraphTraits.d.ts +7 -7
- package/lib/core/graph/GraphTraits.js +16 -16
- package/lib/core/graph/Scc.d.ts +61 -61
- package/lib/core/graph/Scc.js +222 -222
- package/lib/core/graph/ViewTree.d.ts +114 -114
- package/lib/core/graph/ViewTree.js +16 -16
- package/lib/core/graph/builder/CfgBuilder.d.ts +176 -176
- package/lib/core/graph/builder/CfgBuilder.js +1139 -1139
- package/lib/core/graph/builder/ConditionBuilder.d.ts +15 -15
- package/lib/core/graph/builder/ConditionBuilder.js +252 -252
- package/lib/core/graph/builder/LoopBuilder.d.ts +20 -20
- package/lib/core/graph/builder/LoopBuilder.js +251 -251
- package/lib/core/graph/builder/SwitchBuilder.d.ts +11 -11
- package/lib/core/graph/builder/SwitchBuilder.js +152 -152
- package/lib/core/graph/builder/TrapBuilder.d.ts +16 -16
- package/lib/core/graph/builder/TrapBuilder.js +272 -272
- package/lib/core/graph/builder/ViewTreeBuilder.d.ts +203 -203
- package/lib/core/graph/builder/ViewTreeBuilder.js +1055 -1055
- package/lib/core/model/ArkBaseModel.d.ts +59 -59
- package/lib/core/model/ArkBaseModel.js +274 -274
- package/lib/core/model/ArkBody.d.ts +24 -24
- package/lib/core/model/ArkBody.js +65 -65
- package/lib/core/model/ArkClass.d.ts +206 -206
- package/lib/core/model/ArkClass.js +439 -439
- package/lib/core/model/ArkExport.d.ts +72 -72
- package/lib/core/model/ArkExport.js +147 -147
- package/lib/core/model/ArkField.d.ts +62 -62
- package/lib/core/model/ArkField.js +113 -113
- package/lib/core/model/ArkFile.d.ts +131 -131
- package/lib/core/model/ArkFile.js +267 -267
- package/lib/core/model/ArkImport.d.ts +44 -44
- package/lib/core/model/ArkImport.js +108 -108
- package/lib/core/model/ArkMetadata.d.ts +31 -31
- package/lib/core/model/ArkMetadata.js +55 -55
- package/lib/core/model/ArkMethod.d.ts +261 -261
- package/lib/core/model/ArkMethod.js +592 -592
- package/lib/core/model/ArkNamespace.d.ts +66 -66
- package/lib/core/model/ArkNamespace.js +209 -209
- package/lib/core/model/ArkSignature.d.ts +162 -162
- package/lib/core/model/ArkSignature.js +379 -379
- package/lib/core/model/builder/ArkClassBuilder.d.ts +12 -12
- package/lib/core/model/builder/ArkClassBuilder.js +454 -454
- package/lib/core/model/builder/ArkExportBuilder.d.ts +24 -24
- package/lib/core/model/builder/ArkExportBuilder.js +210 -210
- package/lib/core/model/builder/ArkFieldBuilder.d.ts +8 -8
- package/lib/core/model/builder/ArkFieldBuilder.js +193 -193
- package/lib/core/model/builder/ArkFileBuilder.d.ts +9 -9
- package/lib/core/model/builder/ArkFileBuilder.js +165 -165
- package/lib/core/model/builder/ArkImportBuilder.d.ts +4 -4
- package/lib/core/model/builder/ArkImportBuilder.js +128 -128
- package/lib/core/model/builder/ArkMethodBuilder.d.ts +63 -63
- package/lib/core/model/builder/ArkMethodBuilder.js +486 -486
- package/lib/core/model/builder/ArkNamespaceBuilder.d.ts +5 -5
- package/lib/core/model/builder/ArkNamespaceBuilder.js +205 -205
- package/lib/core/model/builder/ArkSignatureBuilder.d.ts +8 -8
- package/lib/core/model/builder/ArkSignatureBuilder.js +40 -40
- package/lib/core/model/builder/BodyBuilder.d.ts +55 -30
- package/lib/core/model/builder/BodyBuilder.d.ts.map +1 -1
- package/lib/core/model/builder/BodyBuilder.js +542 -371
- package/lib/core/model/builder/builderUtils.d.ts +18 -18
- package/lib/core/model/builder/builderUtils.js +558 -558
- package/lib/index.d.ts +82 -80
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +201 -196
- package/lib/save/ArkStream.d.ts +23 -23
- package/lib/save/ArkStream.js +83 -83
- package/lib/save/DotPrinter.d.ts +43 -43
- package/lib/save/DotPrinter.js +170 -170
- package/lib/save/GraphPrinter.d.ts +16 -16
- package/lib/save/GraphPrinter.js +134 -134
- package/lib/save/JsonPrinter.d.ts +30 -30
- package/lib/save/JsonPrinter.js +580 -580
- package/lib/save/Printer.d.ts +12 -12
- package/lib/save/Printer.js +27 -27
- package/lib/save/PrinterBuilder.d.ts +53 -53
- package/lib/save/PrinterBuilder.js +145 -145
- package/lib/save/ViewTreePrinter.d.ts +14 -14
- package/lib/save/ViewTreePrinter.js +123 -123
- package/lib/save/arkir/ArkIRClassPrinter.d.ts +13 -13
- package/lib/save/arkir/ArkIRClassPrinter.js +92 -92
- package/lib/save/arkir/ArkIRFieldPrinter.d.ts +11 -11
- package/lib/save/arkir/ArkIRFieldPrinter.js +64 -64
- package/lib/save/arkir/ArkIRFilePrinter.d.ts +12 -12
- package/lib/save/arkir/ArkIRFilePrinter.js +54 -54
- package/lib/save/arkir/ArkIRMethodPrinter.d.ts +16 -16
- package/lib/save/arkir/ArkIRMethodPrinter.js +159 -159
- package/lib/save/arkir/ArkIRNamespacePrinter.d.ts +11 -11
- package/lib/save/arkir/ArkIRNamespacePrinter.js +66 -66
- package/lib/save/base/BasePrinter.d.ts +23 -23
- package/lib/save/base/BasePrinter.js +70 -70
- package/lib/save/base/ExportPrinter.d.ts +8 -8
- package/lib/save/base/ExportPrinter.js +67 -67
- package/lib/save/base/ImportPrinter.d.ts +9 -9
- package/lib/save/base/ImportPrinter.js +92 -92
- package/lib/save/base/PrinterUtils.d.ts +24 -24
- package/lib/save/base/PrinterUtils.js +208 -208
- package/lib/save/serializeArkIR.d.ts +8 -8
- package/lib/save/serializeArkIR.js +294 -294
- package/lib/save/source/SourceBase.d.ts +22 -22
- package/lib/save/source/SourceBase.js +64 -64
- package/lib/save/source/SourceBody.d.ts +58 -58
- package/lib/save/source/SourceBody.js +296 -296
- package/lib/save/source/SourceClass.d.ts +25 -25
- package/lib/save/source/SourceClass.js +187 -187
- package/lib/save/source/SourceField.d.ts +13 -13
- package/lib/save/source/SourceField.js +73 -73
- package/lib/save/source/SourceFilePrinter.d.ts +12 -12
- package/lib/save/source/SourceFilePrinter.js +69 -69
- package/lib/save/source/SourceMethod.d.ts +22 -22
- package/lib/save/source/SourceMethod.d.ts.map +1 -1
- package/lib/save/source/SourceMethod.js +196 -193
- package/lib/save/source/SourceNamespace.d.ts +11 -11
- package/lib/save/source/SourceNamespace.js +83 -83
- package/lib/save/source/SourceStmt.d.ts +178 -178
- package/lib/save/source/SourceStmt.js +838 -838
- package/lib/save/source/SourceTransformer.d.ts +46 -46
- package/lib/save/source/SourceTransformer.js +446 -446
- package/lib/transformer/FunctionTransformer.d.ts +2 -2
- package/lib/transformer/FunctionTransformer.js +17 -17
- package/lib/transformer/SceneTransformer.d.ts +2 -2
- package/lib/transformer/SceneTransformer.js +17 -17
- package/lib/transformer/StaticSingleAssignmentFormer.d.ts +12 -12
- package/lib/transformer/StaticSingleAssignmentFormer.js +259 -259
- package/lib/transformer/Transformer.d.ts +6 -6
- package/lib/transformer/Transformer.js +22 -22
- package/lib/utils/AstTreeUtils.d.ts +4 -4
- package/lib/utils/AstTreeUtils.js +26 -26
- package/lib/utils/CfgStructualAnalysis.d.ts +110 -110
- package/lib/utils/CfgStructualAnalysis.js +1277 -1277
- package/lib/utils/FileUtils.d.ts +18 -18
- package/lib/utils/FileUtils.js +135 -135
- package/lib/utils/SparseBitVector.d.ts +100 -100
- package/lib/utils/SparseBitVector.js +445 -445
- package/lib/utils/callGraphUtils.d.ts +30 -30
- package/lib/utils/callGraphUtils.js +205 -205
- package/lib/utils/crypto_utils.d.ts +5 -5
- package/lib/utils/crypto_utils.js +57 -57
- package/lib/utils/entryMethodUtils.d.ts +13 -13
- package/lib/utils/entryMethodUtils.js +110 -110
- package/lib/utils/getAllFiles.d.ts +9 -9
- package/lib/utils/getAllFiles.js +90 -90
- package/lib/utils/json5parser.d.ts +6 -6
- package/lib/utils/json5parser.js +146 -146
- package/lib/utils/logger.d.ts +18 -18
- package/lib/utils/logger.d.ts.map +1 -1
- package/lib/utils/logger.js +97 -90
- package/lib/utils/pathTransfer.d.ts +1 -1
- package/lib/utils/pathTransfer.js +25 -25
- package/node_modules/json5/lib/cli.js +0 -0
- package/node_modules/ohos-typescript/bin/tsc +0 -0
- package/node_modules/ohos-typescript/bin/tsserver +0 -0
- package/package.json +3 -3
|
@@ -1,1399 +1,1399 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright (c) 2024-2025 Huawei Device Co., Ltd.
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
-
if (k2 === undefined) k2 = k;
|
|
18
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
-
}
|
|
22
|
-
Object.defineProperty(o, k2, desc);
|
|
23
|
-
}) : (function(o, m, k, k2) {
|
|
24
|
-
if (k2 === undefined) k2 = k;
|
|
25
|
-
o[k2] = m[k];
|
|
26
|
-
}));
|
|
27
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
-
}) : function(o, v) {
|
|
30
|
-
o["default"] = v;
|
|
31
|
-
});
|
|
32
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
33
|
-
if (mod && mod.__esModule) return mod;
|
|
34
|
-
var result = {};
|
|
35
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
36
|
-
__setModuleDefault(result, mod);
|
|
37
|
-
return result;
|
|
38
|
-
};
|
|
39
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.PagBuilder = exports.CSFuncID = void 0;
|
|
41
|
-
const CallGraph_1 = require("../model/CallGraph");
|
|
42
|
-
const Stmt_1 = require("../../core/base/Stmt");
|
|
43
|
-
const Expr_1 = require("../../core/base/Expr");
|
|
44
|
-
const Ref_1 = require("../../core/base/Ref");
|
|
45
|
-
const logger_1 = __importStar(require("../../utils/logger"));
|
|
46
|
-
const Local_1 = require("../../core/base/Local");
|
|
47
|
-
const Type_1 = require("../../core/base/Type");
|
|
48
|
-
const Constant_1 = require("../../core/base/Constant");
|
|
49
|
-
const Statistics_1 = require("../common/Statistics");
|
|
50
|
-
const Context_1 = require("./Context");
|
|
51
|
-
const Pag_1 = require("./Pag");
|
|
52
|
-
const TSConst_1 = require("../../core/common/TSConst");
|
|
53
|
-
const Const_1 = require("../../core/common/Const");
|
|
54
|
-
const PTAUtils_1 = require("./PTAUtils");
|
|
55
|
-
const PointerAnalysisConfig_1 = require("./PointerAnalysisConfig");
|
|
56
|
-
const logger = logger_1.default.getLogger(logger_1.LOG_MODULE_TYPE.ARKANALYZER, 'PTA');
|
|
57
|
-
class CSFuncID {
|
|
58
|
-
constructor(cid, fid) {
|
|
59
|
-
this.cid = cid;
|
|
60
|
-
this.funcID = fid;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
exports.CSFuncID = CSFuncID;
|
|
64
|
-
class PagBuilder {
|
|
65
|
-
constructor(p, cg, s, kLimit) {
|
|
66
|
-
this.handledFunc = new Set();
|
|
67
|
-
this.worklist = [];
|
|
68
|
-
// TODO: change string to hash value
|
|
69
|
-
this.staticField2UniqInstanceMap = new Map();
|
|
70
|
-
this.instanceField2UniqInstanceMap = new Map();
|
|
71
|
-
this.cid2ThisRefPtMap = new Map();
|
|
72
|
-
this.cid2ThisRefMap = new Map();
|
|
73
|
-
this.cid2ThisLocalMap = new Map();
|
|
74
|
-
this.sdkMethodReturnValueMap = new Map();
|
|
75
|
-
// record the SDK API param, and create fake Values
|
|
76
|
-
this.sdkMethodParamValueMap = new Map();
|
|
77
|
-
this.fakeSdkMethodParamDeclaringStmt = new Stmt_1.ArkAssignStmt(new Local_1.Local(""), new Local_1.Local(""));
|
|
78
|
-
this.funcHandledThisRound = new Set();
|
|
79
|
-
this.updatedNodesThisRound = new Map();
|
|
80
|
-
this.singletonFuncMap = new Map();
|
|
81
|
-
this.globalThisValue = new Local_1.Local(TSConst_1.GLOBAL_THIS_NAME);
|
|
82
|
-
this.storagePropertyMap = new Map();
|
|
83
|
-
this.externalScopeVariableMap = new Map();
|
|
84
|
-
this.pag = p;
|
|
85
|
-
this.cg = cg;
|
|
86
|
-
this.funcPags = new Map;
|
|
87
|
-
this.ctx = new Context_1.KLimitedContextSensitive(kLimit);
|
|
88
|
-
this.scene = s;
|
|
89
|
-
this.pagStat = new Statistics_1.PAGStat();
|
|
90
|
-
}
|
|
91
|
-
buildFuncPagAndAddToWorklist(cs) {
|
|
92
|
-
if (this.worklist.includes(cs)) {
|
|
93
|
-
return cs;
|
|
94
|
-
}
|
|
95
|
-
this.buildFuncPag(cs.funcID);
|
|
96
|
-
if (this.isSingletonFunction(cs.funcID)) {
|
|
97
|
-
cs.cid = Context_1.DUMMY_CID;
|
|
98
|
-
}
|
|
99
|
-
this.worklist.push(cs);
|
|
100
|
-
return cs;
|
|
101
|
-
}
|
|
102
|
-
addToFuncHandledListThisRound(id) {
|
|
103
|
-
if (this.funcHandledThisRound.has(id)) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
this.funcHandledThisRound.add(id);
|
|
107
|
-
}
|
|
108
|
-
buildForEntries(funcIDs) {
|
|
109
|
-
this.worklist = [];
|
|
110
|
-
funcIDs.forEach(funcID => {
|
|
111
|
-
let cid = this.ctx.getNewContextID(funcID);
|
|
112
|
-
let csFuncID = new CSFuncID(cid, funcID);
|
|
113
|
-
this.buildFuncPagAndAddToWorklist(csFuncID);
|
|
114
|
-
});
|
|
115
|
-
this.handleReachable();
|
|
116
|
-
this.globalThisPagNode = this.getOrNewGlobalThisNode(-1);
|
|
117
|
-
this.pag.addPagEdge(this.globalThisPagNode, this.globalThisPagNode, Pag_1.PagEdgeKind.Copy);
|
|
118
|
-
}
|
|
119
|
-
handleReachable() {
|
|
120
|
-
if (this.worklist.length === 0) {
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
this.funcHandledThisRound.clear();
|
|
124
|
-
while (this.worklist.length > 0) {
|
|
125
|
-
let csFunc = this.worklist.shift();
|
|
126
|
-
this.buildPagFromFuncPag(csFunc.funcID, csFunc.cid);
|
|
127
|
-
this.addToFuncHandledListThisRound(csFunc.funcID);
|
|
128
|
-
}
|
|
129
|
-
return true;
|
|
130
|
-
}
|
|
131
|
-
build() {
|
|
132
|
-
for (let funcID of this.cg.getEntries()) {
|
|
133
|
-
let cid = this.ctx.getNewContextID(funcID);
|
|
134
|
-
let csFuncID = new CSFuncID(cid, funcID);
|
|
135
|
-
this.buildFuncPagAndAddToWorklist(csFuncID);
|
|
136
|
-
this.handleReachable();
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
buildFuncPag(funcID) {
|
|
140
|
-
if (this.funcPags.has(funcID)) {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
let arkMethod = this.cg.getArkMethodByFuncID(funcID);
|
|
144
|
-
if (arkMethod == null) {
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
let cfg = arkMethod.getCfg();
|
|
148
|
-
if (!cfg) {
|
|
149
|
-
this.buildSDKFuncPag(funcID);
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
logger.trace(`[build FuncPag] ${arkMethod.getSignature().toString()}`);
|
|
153
|
-
let fpag = new Pag_1.FuncPag();
|
|
154
|
-
for (let stmt of cfg.getStmts()) {
|
|
155
|
-
if (stmt instanceof Stmt_1.ArkAssignStmt) {
|
|
156
|
-
stmt.getRightOp().getUses().forEach((v) => {
|
|
157
|
-
this.handleValueFromExternalScope(v, funcID);
|
|
158
|
-
});
|
|
159
|
-
// Add non-call edges
|
|
160
|
-
let kind = this.getEdgeKindForAssignStmt(stmt);
|
|
161
|
-
if (kind !== Pag_1.PagEdgeKind.Unknown) {
|
|
162
|
-
fpag.addInternalEdge(stmt, kind);
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
165
|
-
// handle call
|
|
166
|
-
let ivkExpr = stmt.getInvokeExpr();
|
|
167
|
-
if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
|
|
168
|
-
let cs = this.cg.getCallSiteByStmt(stmt);
|
|
169
|
-
if (cs) {
|
|
170
|
-
// direct call is already existing in CG
|
|
171
|
-
// TODO: API Invoke stmt has anonymous method param, how to add these param into callee
|
|
172
|
-
fpag.addNormalCallSite(cs);
|
|
173
|
-
if (ivkExpr.getMethodSignature().getDeclaringClassSignature()
|
|
174
|
-
.getDeclaringFileSignature().getFileName() === Const_1.UNKNOWN_FILE_NAME) {
|
|
175
|
-
fpag.addUnknownCallSite(cs);
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
throw new Error('Can not find static callsite');
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
else if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr || ivkExpr instanceof Expr_1.ArkPtrInvokeExpr) {
|
|
184
|
-
let ptcs = this.cg.getDynCallsiteByStmt(stmt);
|
|
185
|
-
if (ptcs) {
|
|
186
|
-
this.addToDynamicCallSite(fpag, ptcs);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
else if (stmt instanceof Stmt_1.ArkInvokeStmt) {
|
|
191
|
-
// TODO: discuss if we need a invokeStmt
|
|
192
|
-
let cs = this.cg.getCallSiteByStmt(stmt);
|
|
193
|
-
if (cs) {
|
|
194
|
-
// direct call or constructor call is already existing in CG
|
|
195
|
-
// TODO: some ptr invoke stmt is recognized as Static invoke in tests/resources/callgraph/funPtrTest1/fnPtrTest4.ts
|
|
196
|
-
// TODO: instance invoke(ptr invoke)
|
|
197
|
-
if (this.cg.isUnknownMethod(cs.calleeFuncID)) {
|
|
198
|
-
fpag.addUnknownCallSite(cs);
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
fpag.addNormalCallSite(cs);
|
|
202
|
-
}
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
let dycs = this.cg.getDynCallsiteByStmt(stmt);
|
|
206
|
-
if (dycs) {
|
|
207
|
-
this.addToDynamicCallSite(fpag, dycs);
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
throw new Error('Can not find callsite by stmt');
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
// TODO: need handle other type of stmt?
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
this.funcPags.set(funcID, fpag);
|
|
218
|
-
this.pagStat.numTotalFunction++;
|
|
219
|
-
return true;
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* will not create real funcPag, only create param values
|
|
223
|
-
*/
|
|
224
|
-
buildSDKFuncPag(funcID) {
|
|
225
|
-
var _a;
|
|
226
|
-
// check if SDK method
|
|
227
|
-
let cgNode = this.cg.getNode(funcID);
|
|
228
|
-
if (!cgNode.isSdkMethod()) {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
let args = (_a = this.cg.getArkMethodByFuncID(funcID)) === null || _a === void 0 ? void 0 : _a.getParameters();
|
|
232
|
-
if (!args) {
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
let paramArr = [];
|
|
236
|
-
args.forEach((arg) => {
|
|
237
|
-
let argInstance = new Local_1.Local(arg.getName(), arg.getType());
|
|
238
|
-
argInstance.setDeclaringStmt(this.fakeSdkMethodParamDeclaringStmt);
|
|
239
|
-
paramArr.push(argInstance);
|
|
240
|
-
});
|
|
241
|
-
this.sdkMethodParamValueMap.set(funcID, paramArr);
|
|
242
|
-
}
|
|
243
|
-
buildPagFromFuncPag(funcID, cid) {
|
|
244
|
-
var _a;
|
|
245
|
-
let funcPag = this.funcPags.get(funcID);
|
|
246
|
-
if (funcPag === undefined) {
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
if (this.handledFunc.has(`${cid}-${funcID}`)) {
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
this.addEdgesFromFuncPag(funcPag, cid);
|
|
253
|
-
let interFuncPag = (_a = this.interFuncPags) === null || _a === void 0 ? void 0 : _a.get(funcID);
|
|
254
|
-
if (interFuncPag) {
|
|
255
|
-
this.addEdgesFromInterFuncPag(interFuncPag, cid);
|
|
256
|
-
}
|
|
257
|
-
this.addCallsEdgesFromFuncPag(funcPag, cid);
|
|
258
|
-
this.addDynamicCallSite(funcPag, funcID);
|
|
259
|
-
this.addUnknownCallSite(funcPag, funcID);
|
|
260
|
-
this.handledFunc.add(`${cid}-${funcID}`);
|
|
261
|
-
}
|
|
262
|
-
/// Add Pag Nodes and Edges in function
|
|
263
|
-
addEdgesFromFuncPag(funcPag, cid) {
|
|
264
|
-
let inEdges = funcPag.getInternalEdges();
|
|
265
|
-
if (inEdges === undefined) {
|
|
266
|
-
return false;
|
|
267
|
-
}
|
|
268
|
-
for (let e of inEdges) {
|
|
269
|
-
let srcPagNode = this.getOrNewPagNode(cid, e.src, e.stmt);
|
|
270
|
-
let dstPagNode = this.getOrNewPagNode(cid, e.dst, e.stmt);
|
|
271
|
-
this.pag.addPagEdge(srcPagNode, dstPagNode, e.kind, e.stmt);
|
|
272
|
-
// Take place of the real stmt for return
|
|
273
|
-
if (dstPagNode.getStmt() instanceof Stmt_1.ArkReturnStmt) {
|
|
274
|
-
dstPagNode.setStmt(e.stmt);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return true;
|
|
278
|
-
}
|
|
279
|
-
/// add Copy edges interprocedural
|
|
280
|
-
addCallsEdgesFromFuncPag(funcPag, cid) {
|
|
281
|
-
for (let cs of funcPag.getNormalCallSites()) {
|
|
282
|
-
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
283
|
-
let calleeCid = this.ctx.getOrNewContext(cid, cs.calleeFuncID, true);
|
|
284
|
-
let calleeCGNode = this.cg.getNode(cs.calleeFuncID);
|
|
285
|
-
// process the Storage API(Static)
|
|
286
|
-
if (!this.processStorage(cs, calleeCGNode, cid)) {
|
|
287
|
-
// If not Storage API, process normal edge
|
|
288
|
-
this.addStaticPagCallEdge(cs, cid, calleeCid);
|
|
289
|
-
}
|
|
290
|
-
// Add edge to thisRef for special calls
|
|
291
|
-
if (calleeCGNode.getKind() === CallGraph_1.CallGraphNodeKind.constructor ||
|
|
292
|
-
calleeCGNode.getKind() === CallGraph_1.CallGraphNodeKind.intrinsic) {
|
|
293
|
-
let callee = this.scene.getMethod(this.cg.getMethodByFuncID(cs.calleeFuncID));
|
|
294
|
-
if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
295
|
-
let baseNode = this.getOrNewPagNode(cid, ivkExpr.getBase());
|
|
296
|
-
let baseNodeID = baseNode.getID();
|
|
297
|
-
this.addThisRefCallEdge(baseNodeID, cid, ivkExpr, callee, calleeCid, cs.callerFuncID);
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
logger.error(`constructor or intrinsic func is static ${ivkExpr.toString()}`);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
return true;
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* process Storage API
|
|
308
|
-
* @returns boolean: check if the cs represent a Storage API, no matter the API will success or fail
|
|
309
|
-
*/
|
|
310
|
-
processStorage(cs, calleeCGNode, cid) {
|
|
311
|
-
let storageName = calleeCGNode.getMethod().getDeclaringClassSignature().getClassName();
|
|
312
|
-
let storageType = this.getStorageType(storageName, cs, cid);
|
|
313
|
-
// TODO: add other storages
|
|
314
|
-
if (storageType === Pag_1.StorageType.APP_STORAGE) {
|
|
315
|
-
let calleeName = calleeCGNode.getMethod().getMethodSubSignature().getMethodName();
|
|
316
|
-
// TODO: complete AppStorage API
|
|
317
|
-
if (calleeName === 'setOrCreate') {
|
|
318
|
-
this.processStorageSetOrCreate(cs, cid);
|
|
319
|
-
}
|
|
320
|
-
else if (calleeName === 'link') {
|
|
321
|
-
this.processStorageLink(cs, cid);
|
|
322
|
-
}
|
|
323
|
-
else if (calleeName === 'prop') {
|
|
324
|
-
this.processStorageProp(cs, cid);
|
|
325
|
-
}
|
|
326
|
-
else if (calleeName === 'set') {
|
|
327
|
-
this.processStorageSet(cs, cid);
|
|
328
|
-
}
|
|
329
|
-
else if (calleeName === 'get') {
|
|
330
|
-
this.processStorageGet(cs, cid);
|
|
331
|
-
}
|
|
332
|
-
return true;
|
|
333
|
-
}
|
|
334
|
-
else if (storageType === Pag_1.StorageType.LOCAL_STORAGE) {
|
|
335
|
-
// TODO: LocalStorage is not Static
|
|
336
|
-
}
|
|
337
|
-
return false;
|
|
338
|
-
}
|
|
339
|
-
processStorageSetOrCreate(cs, cid) {
|
|
340
|
-
let propertyStr = this.getPropertyName(cs.args[0]);
|
|
341
|
-
if (!propertyStr) {
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
let propertyName = propertyStr;
|
|
345
|
-
let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
|
|
346
|
-
let storageObj = cs.args[1];
|
|
347
|
-
this.addPropertyLinkEdge(propertyNode, storageObj, cid, cs.callStmt, Pag_1.StorageLinkEdgeType.Local2Property);
|
|
348
|
-
}
|
|
349
|
-
processStorageLink(cs, cid) {
|
|
350
|
-
let propertyStr = this.getPropertyName(cs.args[0]);
|
|
351
|
-
if (!propertyStr) {
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
let propertyName = propertyStr;
|
|
355
|
-
let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
|
|
356
|
-
let leftOp = cs.callStmt.getLeftOp();
|
|
357
|
-
let linkedOpNode = this.pag.getOrNewNode(cid, leftOp);
|
|
358
|
-
if (linkedOpNode instanceof Pag_1.PagLocalNode) {
|
|
359
|
-
linkedOpNode.setStorageLink(Pag_1.StorageType.APP_STORAGE, propertyName);
|
|
360
|
-
}
|
|
361
|
-
this.pag.addPagEdge(propertyNode, linkedOpNode, Pag_1.PagEdgeKind.Copy);
|
|
362
|
-
this.pag.addPagEdge(linkedOpNode, propertyNode, Pag_1.PagEdgeKind.Copy);
|
|
363
|
-
}
|
|
364
|
-
processStorageProp(cs, cid) {
|
|
365
|
-
let propertyStr = this.getPropertyName(cs.args[0]);
|
|
366
|
-
if (!propertyStr) {
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
let propertyName = propertyStr;
|
|
370
|
-
let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
|
|
371
|
-
let leftOp = cs.callStmt.getLeftOp();
|
|
372
|
-
let linkedOpNode = this.pag.getOrNewNode(cid, leftOp);
|
|
373
|
-
if (linkedOpNode instanceof Pag_1.PagLocalNode) {
|
|
374
|
-
linkedOpNode.setStorageLink(Pag_1.StorageType.APP_STORAGE, propertyName);
|
|
375
|
-
}
|
|
376
|
-
this.pag.addPagEdge(propertyNode, linkedOpNode, Pag_1.PagEdgeKind.Copy);
|
|
377
|
-
}
|
|
378
|
-
processStorageSet(cs, cid) {
|
|
379
|
-
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
380
|
-
if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
381
|
-
let base = ivkExpr.getBase();
|
|
382
|
-
let baseNode = this.pag.getOrNewNode(cid, base);
|
|
383
|
-
if (baseNode.isStorageLinked()) {
|
|
384
|
-
let argsNode = this.pag.getOrNewNode(cid, cs.args[0]);
|
|
385
|
-
this.pag.addPagEdge(argsNode, baseNode, Pag_1.PagEdgeKind.Copy);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
else if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
|
|
389
|
-
// TODO: process AppStorage.set()
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
processStorageGet(cs, cid) {
|
|
393
|
-
if (!(cs.callStmt instanceof Stmt_1.ArkAssignStmt)) {
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
let leftOp = cs.callStmt.getLeftOp();
|
|
397
|
-
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
398
|
-
let propertyName;
|
|
399
|
-
if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
|
|
400
|
-
let propertyStr = this.getPropertyName(cs.args[0]);
|
|
401
|
-
if (propertyStr) {
|
|
402
|
-
propertyName = propertyStr;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
else if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
406
|
-
let baseNode = this.pag.getOrNewNode(cid, ivkExpr.getBase());
|
|
407
|
-
if (baseNode.isStorageLinked()) {
|
|
408
|
-
propertyName = baseNode.getStorage().PropertyName;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
let propertyNode = this.getPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
|
|
412
|
-
if (!propertyNode) {
|
|
413
|
-
return;
|
|
414
|
-
}
|
|
415
|
-
this.pag.addPagEdge(propertyNode, this.pag.getOrNewNode(cid, leftOp, cs.callStmt), Pag_1.PagEdgeKind.Copy, cs.callStmt);
|
|
416
|
-
}
|
|
417
|
-
getPropertyName(value) {
|
|
418
|
-
if (value instanceof Local_1.Local) {
|
|
419
|
-
let type = value.getType();
|
|
420
|
-
if (type instanceof Type_1.StringType) {
|
|
421
|
-
return type.getName();
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
else if (value instanceof Constant_1.Constant) {
|
|
425
|
-
return value.getValue();
|
|
426
|
-
}
|
|
427
|
-
return undefined;
|
|
428
|
-
}
|
|
429
|
-
addDynamicCallSite(funcPag, funcID) {
|
|
430
|
-
// add dyn callsite in funcpag to base node
|
|
431
|
-
for (let cs of funcPag.getDynamicCallSites()) {
|
|
432
|
-
let invokeExpr = cs.callStmt.getInvokeExpr();
|
|
433
|
-
let base;
|
|
434
|
-
if (invokeExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
435
|
-
base = invokeExpr.getBase();
|
|
436
|
-
}
|
|
437
|
-
else if (invokeExpr instanceof Expr_1.ArkPtrInvokeExpr) {
|
|
438
|
-
base = invokeExpr.getFuncPtrLocal();
|
|
439
|
-
}
|
|
440
|
-
// TODO: check base under different cid
|
|
441
|
-
let baseNodeIDs = this.pag.getNodesByValue(base);
|
|
442
|
-
if (!baseNodeIDs) {
|
|
443
|
-
// bind the call site to export base
|
|
444
|
-
let interProceduralLocal = this.getSourceValueFromExternalScope(base, funcID);
|
|
445
|
-
if (interProceduralLocal) {
|
|
446
|
-
baseNodeIDs = this.pag.getNodesByValue(interProceduralLocal);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
if (!baseNodeIDs) {
|
|
450
|
-
logger.warn(`[build dynamic call site] can not handle call site with base ${base.toString()}`);
|
|
451
|
-
continue;
|
|
452
|
-
}
|
|
453
|
-
for (let nodeID of baseNodeIDs.values()) {
|
|
454
|
-
let node = this.pag.getNode(nodeID);
|
|
455
|
-
if (!(node instanceof Pag_1.PagLocalNode)) {
|
|
456
|
-
continue;
|
|
457
|
-
}
|
|
458
|
-
node.addRelatedDynCallSite(cs);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
addUnknownCallSite(funcPag, funcID) {
|
|
463
|
-
var _a;
|
|
464
|
-
let method = this.cg.getArkMethodByFuncID(funcID);
|
|
465
|
-
if (!method) {
|
|
466
|
-
throw new Error(`can not find ArkMethod by FuncID ${funcID}`);
|
|
467
|
-
}
|
|
468
|
-
let locals = (_a = method.getBody()) === null || _a === void 0 ? void 0 : _a.getLocals();
|
|
469
|
-
funcPag.getUnknownCallSites().forEach((unknownCallSite) => {
|
|
470
|
-
var _a;
|
|
471
|
-
let calleeName = (_a = unknownCallSite.callStmt.getInvokeExpr()) === null || _a === void 0 ? void 0 : _a.getMethodSignature().getMethodSubSignature().getMethodName();
|
|
472
|
-
let base = locals.get(calleeName);
|
|
473
|
-
if (base) {
|
|
474
|
-
let baseNodeIDs = this.pag.getNodesByValue(base);
|
|
475
|
-
if (!baseNodeIDs) {
|
|
476
|
-
logger.warn(`[build dynamic call site] can not handle call site with base ${base.toString()}`);
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
for (let nodeID of baseNodeIDs.values()) {
|
|
480
|
-
let node = this.pag.getNode(nodeID);
|
|
481
|
-
if (!(node instanceof Pag_1.PagLocalNode)) {
|
|
482
|
-
continue;
|
|
483
|
-
}
|
|
484
|
-
node.addRelatedUnknownCallSite(unknownCallSite);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
addDynamicCallEdge(cs, baseClassPTNode, cid) {
|
|
490
|
-
let srcNodes = [];
|
|
491
|
-
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
492
|
-
let ptNode = this.pag.getNode(baseClassPTNode);
|
|
493
|
-
let value = ptNode.getValue();
|
|
494
|
-
let callees = this.getDynamicCallee(ptNode, value, ivkExpr, cs);
|
|
495
|
-
for (let callee of callees) {
|
|
496
|
-
if (!callee) {
|
|
497
|
-
continue;
|
|
498
|
-
}
|
|
499
|
-
// get caller and callee CG node, add param and return value PAG edge
|
|
500
|
-
let dstCGNode = this.cg.getCallGraphNodeByMethod(callee.getSignature());
|
|
501
|
-
let callerNode = this.cg.getNode(cs.callerFuncID);
|
|
502
|
-
if (!callerNode) {
|
|
503
|
-
throw new Error("Can not get caller method node");
|
|
504
|
-
}
|
|
505
|
-
// update call graph
|
|
506
|
-
// TODO: movo to cgbuilder
|
|
507
|
-
this.cg.addDynamicCallEdge(callerNode.getID(), dstCGNode.getID(), cs.callStmt);
|
|
508
|
-
if (!this.cg.detectReachable(dstCGNode.getID(), callerNode.getID())) {
|
|
509
|
-
let calleeCid = this.ctx.getOrNewContext(cid, dstCGNode.getID(), true);
|
|
510
|
-
let staticCS = new CallGraph_1.CallSite(cs.callStmt, cs.args, dstCGNode.getID(), cs.callerFuncID);
|
|
511
|
-
srcNodes.push(...this.processContainerPagCallEdge(staticCS, cid, baseClassPTNode));
|
|
512
|
-
srcNodes.push(...this.addStaticPagCallEdge(staticCS, cid, calleeCid));
|
|
513
|
-
// Pass base's pts to callee's this pointer
|
|
514
|
-
if (!dstCGNode.isSdkMethod() && ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
515
|
-
let srcBaseNode = this.addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, cs.callerFuncID);
|
|
516
|
-
srcNodes.push(srcBaseNode);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
return srcNodes;
|
|
521
|
-
}
|
|
522
|
-
getDynamicCallee(ptNode, value, ivkExpr, cs) {
|
|
523
|
-
let callee = [];
|
|
524
|
-
if (ptNode instanceof Pag_1.PagFuncNode) {
|
|
525
|
-
// function ptr invoke
|
|
526
|
-
let tempCallee = this.scene.getMethod(ptNode.getMethod());
|
|
527
|
-
if (!callee) {
|
|
528
|
-
return callee;
|
|
529
|
-
}
|
|
530
|
-
callee.push(tempCallee);
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
let calleeName = ivkExpr.getMethodSignature().getMethodSubSignature().getMethodName();
|
|
534
|
-
// instance method invoke
|
|
535
|
-
if (!(value instanceof Expr_1.ArkNewExpr || value instanceof Expr_1.ArkNewArrayExpr)) {
|
|
536
|
-
return callee;
|
|
537
|
-
}
|
|
538
|
-
let tempCallee;
|
|
539
|
-
// try to get callee by MethodSignature
|
|
540
|
-
if (value instanceof Expr_1.ArkNewExpr) {
|
|
541
|
-
// get class signature
|
|
542
|
-
let clsSig = value.getType().getClassSignature();
|
|
543
|
-
let cls;
|
|
544
|
-
cls = this.scene.getClass(clsSig);
|
|
545
|
-
while (!tempCallee && cls) {
|
|
546
|
-
tempCallee = cls.getMethodWithName(calleeName);
|
|
547
|
-
cls = cls.getSuperClass();
|
|
548
|
-
}
|
|
549
|
-
if (!tempCallee) {
|
|
550
|
-
tempCallee = this.scene.getMethod(ivkExpr.getMethodSignature());
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
if (!tempCallee && cs.args) {
|
|
554
|
-
// while pts has {o_1, o_2} and invoke expr represents a method that only {o_1} has
|
|
555
|
-
// return empty node when {o_2} come in
|
|
556
|
-
// try to get callee by anonymous method in param
|
|
557
|
-
for (let arg of cs.args) {
|
|
558
|
-
// TODO: anonymous method param and return value pointer pass
|
|
559
|
-
let argType = arg.getType();
|
|
560
|
-
if (argType instanceof Type_1.FunctionType) {
|
|
561
|
-
callee.push(this.scene.getMethod(argType.getMethodSignature()));
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
else if (tempCallee) {
|
|
566
|
-
callee.push(tempCallee);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
return callee;
|
|
570
|
-
}
|
|
571
|
-
addUpdatedNode(nodeID, diffPT) {
|
|
572
|
-
var _a;
|
|
573
|
-
let ptaConfig = PointerAnalysisConfig_1.PointerAnalysisConfig.getInstance();
|
|
574
|
-
let updatedNode = (_a = this.updatedNodesThisRound.get(nodeID)) !== null && _a !== void 0 ? _a : new ptaConfig.ptsCollectionCtor();
|
|
575
|
-
updatedNode.union(diffPT);
|
|
576
|
-
this.updatedNodesThisRound.set(nodeID, updatedNode);
|
|
577
|
-
}
|
|
578
|
-
getUpdatedNodes() {
|
|
579
|
-
return this.updatedNodesThisRound;
|
|
580
|
-
}
|
|
581
|
-
resetUpdatedNodes() {
|
|
582
|
-
this.updatedNodesThisRound.clear();
|
|
583
|
-
}
|
|
584
|
-
handleUnkownDynamicCall(cs, cid) {
|
|
585
|
-
var _a;
|
|
586
|
-
let srcNodes = [];
|
|
587
|
-
let callerNode = this.cg.getNode(cs.callerFuncID);
|
|
588
|
-
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
589
|
-
logger.warn("Handling unknown dyn call site : \n " + callerNode.getMethod().toString()
|
|
590
|
-
+ '\n --> ' + ivkExpr.toString() + '\n CID: ' + cid);
|
|
591
|
-
let callees = [];
|
|
592
|
-
let callee = null;
|
|
593
|
-
callee = this.scene.getMethod(ivkExpr.getMethodSignature());
|
|
594
|
-
if (!callee) {
|
|
595
|
-
(_a = cs.args) === null || _a === void 0 ? void 0 : _a.forEach(arg => {
|
|
596
|
-
if (arg.getType() instanceof Type_1.FunctionType) {
|
|
597
|
-
callee = this.scene.getMethod(arg.getType().getMethodSignature());
|
|
598
|
-
if (callee) {
|
|
599
|
-
callees.push(callee);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
});
|
|
603
|
-
}
|
|
604
|
-
else {
|
|
605
|
-
callees.push(callee);
|
|
606
|
-
}
|
|
607
|
-
if (callees.length === 0) {
|
|
608
|
-
return srcNodes;
|
|
609
|
-
}
|
|
610
|
-
callees.forEach(callee => {
|
|
611
|
-
let dstCGNode = this.cg.getCallGraphNodeByMethod(callee.getSignature());
|
|
612
|
-
if (!callerNode) {
|
|
613
|
-
throw new Error("Can not get caller method node");
|
|
614
|
-
}
|
|
615
|
-
if (this.processStorage(cs, dstCGNode, cid)) {
|
|
616
|
-
if (ivkExpr.getArgs().length !== 0) {
|
|
617
|
-
// for AppStorage.set() instance invoke, add obj to reanalyze list
|
|
618
|
-
let argsNode = this.pag.getOrNewNode(cid, cs.args[0]);
|
|
619
|
-
srcNodes.push(argsNode.getID());
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
logger.warn(`\tAdd call edge of unknown call ${callee.getSignature().toString()}`);
|
|
623
|
-
this.cg.addDynamicCallEdge(callerNode.getID(), dstCGNode.getID(), cs.callStmt);
|
|
624
|
-
if (!this.cg.detectReachable(dstCGNode.getID(), callerNode.getID())) {
|
|
625
|
-
let calleeCid = this.ctx.getOrNewContext(cid, dstCGNode.getID(), true);
|
|
626
|
-
let staticCS = new CallGraph_1.CallSite(cs.callStmt, cs.args, dstCGNode.getID(), cs.callerFuncID);
|
|
627
|
-
let staticSrcNodes = this.addStaticPagCallEdge(staticCS, cid, calleeCid);
|
|
628
|
-
srcNodes.push(...staticSrcNodes);
|
|
629
|
-
}
|
|
630
|
-
});
|
|
631
|
-
return srcNodes;
|
|
632
|
-
}
|
|
633
|
-
handleUnprocessedCallSites(processedCallSites) {
|
|
634
|
-
let reAnalyzeNodes = [];
|
|
635
|
-
for (let funcID of this.funcHandledThisRound) {
|
|
636
|
-
let funcPag = this.funcPags.get(funcID);
|
|
637
|
-
if (!funcPag) {
|
|
638
|
-
logger.error(`can not find funcPag of handled func ${funcID}`);
|
|
639
|
-
continue;
|
|
640
|
-
}
|
|
641
|
-
let callSites = funcPag.getDynamicCallSites();
|
|
642
|
-
const diffCallSites = new Set(Array.from(callSites).filter(item => !processedCallSites.has(item)));
|
|
643
|
-
diffCallSites.forEach((cs) => {
|
|
644
|
-
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
645
|
-
if (!(ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr)) {
|
|
646
|
-
return;
|
|
647
|
-
}
|
|
648
|
-
// Get local of base class
|
|
649
|
-
let base = ivkExpr.getBase();
|
|
650
|
-
// TODO: remove this after multiple this local fixed
|
|
651
|
-
base = this.getRealThisLocal(base, cs.callerFuncID);
|
|
652
|
-
// Get PAG nodes for this base's local
|
|
653
|
-
let ctx2NdMap = this.pag.getNodesByValue(base);
|
|
654
|
-
if (!ctx2NdMap) {
|
|
655
|
-
return;
|
|
656
|
-
}
|
|
657
|
-
for (let [cid] of ctx2NdMap.entries()) {
|
|
658
|
-
reAnalyzeNodes.push(...this.handleUnkownDynamicCall(cs, cid));
|
|
659
|
-
}
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
return reAnalyzeNodes;
|
|
663
|
-
}
|
|
664
|
-
addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, callerFunID) {
|
|
665
|
-
var _a;
|
|
666
|
-
if (!callee || !callee.getCfg()) {
|
|
667
|
-
logger.error(`callee is null`);
|
|
668
|
-
return -1;
|
|
669
|
-
}
|
|
670
|
-
let thisAssignStmt = (_a = callee.getCfg()) === null || _a === void 0 ? void 0 : _a.getStmts().filter(s => s instanceof Stmt_1.ArkAssignStmt && s.getRightOp() instanceof Ref_1.ArkThisRef);
|
|
671
|
-
let thisPtr = (thisAssignStmt === null || thisAssignStmt === void 0 ? void 0 : thisAssignStmt.at(0)).getRightOp();
|
|
672
|
-
if (!thisPtr) {
|
|
673
|
-
throw new Error('Can not get this ptr');
|
|
674
|
-
}
|
|
675
|
-
// IMPORTANT: set cid 2 base Pt info firstly
|
|
676
|
-
this.cid2ThisRefPtMap.set(calleeCid, baseClassPTNode);
|
|
677
|
-
let thisRefNode = this.getOrNewThisRefNode(calleeCid, thisPtr);
|
|
678
|
-
thisRefNode.addPTNode(baseClassPTNode);
|
|
679
|
-
let srcBaseLocal = ivkExpr.getBase();
|
|
680
|
-
srcBaseLocal = this.getRealThisLocal(srcBaseLocal, callerFunID);
|
|
681
|
-
let srcNodeId = this.pag.hasCtxNode(cid, srcBaseLocal);
|
|
682
|
-
if (!srcNodeId) {
|
|
683
|
-
// this check is for export local and closure use
|
|
684
|
-
// replace the invoke base, because its origin base has no pag node
|
|
685
|
-
let interProceduralLocal = this.getSourceValueFromExternalScope(srcBaseLocal, callerFunID);
|
|
686
|
-
if (interProceduralLocal) {
|
|
687
|
-
srcNodeId = this.pag.hasCtxNode(cid, interProceduralLocal);
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
if (!srcNodeId) {
|
|
691
|
-
throw new Error('Can not get base node');
|
|
692
|
-
}
|
|
693
|
-
this.pag.addPagEdge(this.pag.getNode(srcNodeId), thisRefNode, Pag_1.PagEdgeKind.This);
|
|
694
|
-
return srcNodeId;
|
|
695
|
-
}
|
|
696
|
-
/*
|
|
697
|
-
* Add copy edges from arguments to parameters
|
|
698
|
-
* ret edges from return values to callsite
|
|
699
|
-
* Return src node
|
|
700
|
-
*/
|
|
701
|
-
addStaticPagCallEdge(cs, callerCid, calleeCid) {
|
|
702
|
-
var _a, _b;
|
|
703
|
-
if (!calleeCid) {
|
|
704
|
-
calleeCid = this.ctx.getOrNewContext(callerCid, cs.calleeFuncID, true);
|
|
705
|
-
}
|
|
706
|
-
let srcNodes = [];
|
|
707
|
-
// Add reachable
|
|
708
|
-
let calleeNode = this.cg.getNode(cs.calleeFuncID);
|
|
709
|
-
let calleeMethod = this.scene.getMethod(calleeNode.getMethod());
|
|
710
|
-
if (!calleeMethod) {
|
|
711
|
-
// TODO: check if nodes need to delete
|
|
712
|
-
return srcNodes;
|
|
713
|
-
}
|
|
714
|
-
if (calleeNode.isSdkMethod()) {
|
|
715
|
-
srcNodes.push(...this.addSDKMethodPagCallEdge(cs, callerCid, calleeCid));
|
|
716
|
-
return srcNodes;
|
|
717
|
-
}
|
|
718
|
-
if (!calleeMethod.getCfg()) {
|
|
719
|
-
// method have no cfg body
|
|
720
|
-
return srcNodes;
|
|
721
|
-
}
|
|
722
|
-
let calleeCS = this.buildFuncPagAndAddToWorklist(new CSFuncID(calleeCid, cs.calleeFuncID));
|
|
723
|
-
// callee cid will updated if callee is singleton
|
|
724
|
-
calleeCid = calleeCS.cid;
|
|
725
|
-
// TODO: getParameterInstances's performance is not good. Need to refactor
|
|
726
|
-
let params = calleeMethod.getCfg().getStmts()
|
|
727
|
-
.filter(stmt => stmt instanceof Stmt_1.ArkAssignStmt && stmt.getRightOp() instanceof Ref_1.ArkParameterRef)
|
|
728
|
-
.map(stmt => stmt.getRightOp());
|
|
729
|
-
let argNum = (_a = cs.args) === null || _a === void 0 ? void 0 : _a.length;
|
|
730
|
-
if (argNum) {
|
|
731
|
-
// add args to parameters edges
|
|
732
|
-
for (let i = 0; i < argNum; i++) {
|
|
733
|
-
let arg = (_b = cs.args) === null || _b === void 0 ? void 0 : _b.at(i);
|
|
734
|
-
let param = params.at(i);
|
|
735
|
-
// TODO: param type should be ArkParameterRef?
|
|
736
|
-
if (arg && param) {
|
|
737
|
-
if (arg instanceof Constant_1.Constant) {
|
|
738
|
-
continue;
|
|
739
|
-
}
|
|
740
|
-
if (arg instanceof Expr_1.AbstractExpr) {
|
|
741
|
-
// TODO: handle this
|
|
742
|
-
continue;
|
|
743
|
-
}
|
|
744
|
-
// Get or create new PAG node for argument and parameter
|
|
745
|
-
let srcPagNode = this.getOrNewPagNode(callerCid, arg, cs.callStmt);
|
|
746
|
-
let dstPagNode = this.getOrNewPagNode(calleeCid, param, cs.callStmt);
|
|
747
|
-
this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
|
|
748
|
-
srcNodes.push(srcPagNode.getID());
|
|
749
|
-
}
|
|
750
|
-
// TODO: handle other types of parmeters
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
// add ret to caller edges
|
|
754
|
-
let retStmts = calleeMethod.getReturnStmt();
|
|
755
|
-
// TODO: call statement must be a assignment state
|
|
756
|
-
if (cs.callStmt instanceof Stmt_1.ArkAssignStmt) {
|
|
757
|
-
let retDst = cs.callStmt.getLeftOp();
|
|
758
|
-
for (let retStmt of retStmts) {
|
|
759
|
-
let retValue = retStmt.getOp();
|
|
760
|
-
if (retValue instanceof Local_1.Local) {
|
|
761
|
-
let srcPagNode = this.getOrNewPagNode(calleeCid, retValue, retStmt);
|
|
762
|
-
let dstPagNode = this.getOrNewPagNode(callerCid, retDst, cs.callStmt);
|
|
763
|
-
this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, retStmt);
|
|
764
|
-
}
|
|
765
|
-
else if (retValue instanceof Constant_1.Constant) {
|
|
766
|
-
continue;
|
|
767
|
-
}
|
|
768
|
-
else if (retValue instanceof Expr_1.AbstractExpr) {
|
|
769
|
-
logger.debug(retValue);
|
|
770
|
-
continue;
|
|
771
|
-
}
|
|
772
|
-
else {
|
|
773
|
-
throw new Error('return dst not a local or constant, but: ' + retValue.getType().toString());
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
return srcNodes;
|
|
778
|
-
}
|
|
779
|
-
addSDKMethodPagCallEdge(cs, callerCid, calleeCid) {
|
|
780
|
-
let srcNodes = [];
|
|
781
|
-
let calleeNode = this.cg.getNode(cs.calleeFuncID);
|
|
782
|
-
let calleeMethod = this.scene.getMethod(calleeNode.getMethod());
|
|
783
|
-
if (!calleeMethod) {
|
|
784
|
-
return srcNodes;
|
|
785
|
-
}
|
|
786
|
-
// block the container SDK
|
|
787
|
-
if ((0, PTAUtils_1.IsCollectionAPI)(calleeMethod.getSignature())) {
|
|
788
|
-
return srcNodes;
|
|
789
|
-
}
|
|
790
|
-
if (!this.sdkMethodParamValueMap.has(calleeNode.getID())) {
|
|
791
|
-
this.buildSDKFuncPag(calleeNode.getID());
|
|
792
|
-
}
|
|
793
|
-
this.addSDKMethodReturnPagEdge(cs, callerCid, calleeCid, calleeMethod);
|
|
794
|
-
srcNodes.push(...this.addSDKMethodParamPagEdge(cs, callerCid, calleeCid, calleeNode.getID()));
|
|
795
|
-
return srcNodes;
|
|
796
|
-
}
|
|
797
|
-
addSDKMethodReturnPagEdge(cs, callerCid, calleeCid, calleeMethod) {
|
|
798
|
-
let returnType = calleeMethod.getReturnType();
|
|
799
|
-
if (!(returnType instanceof Type_1.ClassType) || !(cs.callStmt instanceof Stmt_1.ArkAssignStmt)) {
|
|
800
|
-
return;
|
|
801
|
-
}
|
|
802
|
-
// check fake heap object exists or not
|
|
803
|
-
let cidMap = this.sdkMethodReturnValueMap.get(calleeMethod);
|
|
804
|
-
if (!cidMap) {
|
|
805
|
-
cidMap = new Map();
|
|
806
|
-
}
|
|
807
|
-
let newExpr = cidMap.get(calleeCid);
|
|
808
|
-
if (!newExpr) {
|
|
809
|
-
if (returnType instanceof Type_1.ClassType) {
|
|
810
|
-
newExpr = new Expr_1.ArkNewExpr(returnType);
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
cidMap.set(calleeCid, newExpr);
|
|
814
|
-
this.sdkMethodReturnValueMap.set(calleeMethod, cidMap);
|
|
815
|
-
let srcPagNode = this.getOrNewPagNode(calleeCid, newExpr);
|
|
816
|
-
let dstPagNode = this.getOrNewPagNode(callerCid, cs.callStmt.getLeftOp(), cs.callStmt);
|
|
817
|
-
this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Address, cs.callStmt);
|
|
818
|
-
}
|
|
819
|
-
addSDKMethodParamPagEdge(cs, callerCid, calleeCid, funcID) {
|
|
820
|
-
var _a, _b;
|
|
821
|
-
let argNum = (_a = cs.args) === null || _a === void 0 ? void 0 : _a.length;
|
|
822
|
-
let srcNodes = [];
|
|
823
|
-
if (argNum) {
|
|
824
|
-
// add args to parameters edges
|
|
825
|
-
for (let i = 0; i < argNum; i++) {
|
|
826
|
-
let arg = (_b = cs.args) === null || _b === void 0 ? void 0 : _b.at(i);
|
|
827
|
-
let paramValue;
|
|
828
|
-
if (arg instanceof Local_1.Local && arg.getType() instanceof Type_1.FunctionType) {
|
|
829
|
-
// TODO: cannot find value
|
|
830
|
-
paramValue = this.sdkMethodParamValueMap.get(funcID)[i];
|
|
831
|
-
}
|
|
832
|
-
else {
|
|
833
|
-
continue;
|
|
834
|
-
}
|
|
835
|
-
if (arg && paramValue) {
|
|
836
|
-
// Get or create new PAG node for argument and parameter
|
|
837
|
-
let srcPagNode = this.getOrNewPagNode(callerCid, arg, cs.callStmt);
|
|
838
|
-
let dstPagNode = this.getOrNewPagNode(calleeCid, paramValue, cs.callStmt);
|
|
839
|
-
if (dstPagNode instanceof Pag_1.PagLocalNode) {
|
|
840
|
-
// set the fake param Value in PagLocalNode
|
|
841
|
-
/**
|
|
842
|
-
* TODO: !!!
|
|
843
|
-
* some API param is in the form of anonymous method:
|
|
844
|
-
* component/common.d.ts
|
|
845
|
-
* declare function animateTo(value: AnimateParam, event: () => void): void;
|
|
846
|
-
*
|
|
847
|
-
* this param fake Value will create PagFuncNode rather than PagLocalNode
|
|
848
|
-
* when this API is called, the anonymous method pointer will not be able to pass into the fake Value PagNode
|
|
849
|
-
*/
|
|
850
|
-
dstPagNode.setSdkParam();
|
|
851
|
-
let sdkParamInvokeStmt = new Stmt_1.ArkInvokeStmt(new Expr_1.ArkPtrInvokeExpr(arg.getType().getMethodSignature(), paramValue, []));
|
|
852
|
-
// create new DynCallSite
|
|
853
|
-
let sdkParamCallSite = new CallGraph_1.DynCallSite(funcID, sdkParamInvokeStmt, undefined, undefined);
|
|
854
|
-
dstPagNode.addRelatedDynCallSite(sdkParamCallSite);
|
|
855
|
-
}
|
|
856
|
-
this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
|
|
857
|
-
srcNodes.push(srcPagNode.getID());
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
return srcNodes;
|
|
862
|
-
}
|
|
863
|
-
processContainerPagCallEdge(cs, cid, baseClassPTNode) {
|
|
864
|
-
let srcNodes = [];
|
|
865
|
-
let calleeNode = this.cg.getNode(cs.calleeFuncID);
|
|
866
|
-
let calleeMethod = this.scene.getMethod(calleeNode.getMethod());
|
|
867
|
-
let ptNode = this.pag.getNode(baseClassPTNode);
|
|
868
|
-
if (!calleeMethod || !(ptNode instanceof Pag_1.PagNewContainerExprNode)) {
|
|
869
|
-
return srcNodes;
|
|
870
|
-
}
|
|
871
|
-
let containerValue = cs.callStmt.getInvokeExpr().getBase();
|
|
872
|
-
const containerValueProcess = (argIndex) => {
|
|
873
|
-
let srcNode = this.pag.getOrNewNode(cid, cs.args[argIndex], cs.callStmt);
|
|
874
|
-
let realContainerFieldPagNode = this.pag.getOrClonePagContainerFieldNode(baseClassPTNode, undefined, containerValue);
|
|
875
|
-
if (realContainerFieldPagNode) {
|
|
876
|
-
// In some cases, the value of a variable of array type may not be an explicit array object,
|
|
877
|
-
// and the value of `realContainerFieldPagNode` will be undefined.
|
|
878
|
-
this.pag.addPagEdge(srcNode, realContainerFieldPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
|
|
879
|
-
srcNodes.push(srcNode.getID());
|
|
880
|
-
}
|
|
881
|
-
};
|
|
882
|
-
if ((0, PTAUtils_1.IsCollectionSetAdd)(calleeMethod.getSignature())) {
|
|
883
|
-
containerValueProcess(0);
|
|
884
|
-
}
|
|
885
|
-
else if ((0, PTAUtils_1.IsCollectionMapSet)(calleeMethod.getSignature())) {
|
|
886
|
-
containerValueProcess(1);
|
|
887
|
-
}
|
|
888
|
-
return srcNodes;
|
|
889
|
-
}
|
|
890
|
-
getOrNewPagNode(cid, v, s) {
|
|
891
|
-
if (v instanceof Ref_1.ArkThisRef) {
|
|
892
|
-
return this.getOrNewThisRefNode(cid, v);
|
|
893
|
-
}
|
|
894
|
-
// this local is also not uniq!!!
|
|
895
|
-
// remove below block once this issue fixed
|
|
896
|
-
// globalThis process can not be removed while all `globalThis` ref is the same Value
|
|
897
|
-
if (v instanceof Local_1.Local) {
|
|
898
|
-
if (v.getName() === "this") {
|
|
899
|
-
return this.getOrNewThisLoalNode(cid, v, s);
|
|
900
|
-
}
|
|
901
|
-
else if (v.getName() === TSConst_1.GLOBAL_THIS_NAME && v.getDeclaringStmt() == null) {
|
|
902
|
-
// globalThis node has no cid
|
|
903
|
-
return this.getOrNewGlobalThisNode(-1);
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
if (v instanceof Ref_1.ArkInstanceFieldRef || v instanceof Ref_1.ArkStaticFieldRef) {
|
|
907
|
-
v = this.getRealInstanceRef(v);
|
|
908
|
-
}
|
|
909
|
-
return this.pag.getOrNewNode(cid, v, s);
|
|
910
|
-
}
|
|
911
|
-
/**
|
|
912
|
-
* return ThisRef PAG node according to cid, a cid has a unique ThisRef node
|
|
913
|
-
* @param cid: current contextID
|
|
914
|
-
*/
|
|
915
|
-
getOrNewThisRefNode(cid, v) {
|
|
916
|
-
let thisRefNodeID = this.cid2ThisRefMap.get(cid);
|
|
917
|
-
if (!thisRefNodeID) {
|
|
918
|
-
thisRefNodeID = -1;
|
|
919
|
-
}
|
|
920
|
-
let thisRefNode = this.pag.getOrNewThisRefNode(thisRefNodeID, v);
|
|
921
|
-
this.cid2ThisRefMap.set(cid, thisRefNode.getID());
|
|
922
|
-
return thisRefNode;
|
|
923
|
-
}
|
|
924
|
-
// TODO: remove it once this local not uniq issue is fixed
|
|
925
|
-
getOrNewThisLoalNode(cid, v, s) {
|
|
926
|
-
let thisLocalNodeID = this.cid2ThisLocalMap.get(cid);
|
|
927
|
-
if (thisLocalNodeID) {
|
|
928
|
-
return this.pag.getNode(thisLocalNodeID);
|
|
929
|
-
}
|
|
930
|
-
let thisNode = this.pag.getOrNewNode(cid, v, s);
|
|
931
|
-
this.cid2ThisLocalMap.set(cid, thisNode.getID());
|
|
932
|
-
return thisNode;
|
|
933
|
-
}
|
|
934
|
-
getOrNewGlobalThisNode(cid) {
|
|
935
|
-
return this.pag.getOrNewNode(cid, this.getGlobalThisValue());
|
|
936
|
-
}
|
|
937
|
-
getUniqThisLocalNode(cid) {
|
|
938
|
-
return this.cid2ThisLocalMap.get(cid);
|
|
939
|
-
}
|
|
940
|
-
/**
|
|
941
|
-
* search the storage map to get propertyNode with given storage and propertyFieldName
|
|
942
|
-
* @param storage storage type: AppStorage, LocalStorage etc.
|
|
943
|
-
* @param propertyName string property key
|
|
944
|
-
* @returns propertyNode: PagLocalNode
|
|
945
|
-
*/
|
|
946
|
-
getOrNewPropertyNode(storage, propertyName, stmt) {
|
|
947
|
-
let propertyNode = this.getPropertyNode(storage, propertyName, stmt);
|
|
948
|
-
if (propertyNode) {
|
|
949
|
-
return propertyNode;
|
|
950
|
-
}
|
|
951
|
-
let storageMap = this.storagePropertyMap.get(storage);
|
|
952
|
-
let propertyLocal = new Local_1.Local(propertyName);
|
|
953
|
-
storageMap.set(propertyName, propertyLocal);
|
|
954
|
-
this.storagePropertyMap.set(storage, storageMap);
|
|
955
|
-
return this.getOrNewPagNode(-1, propertyLocal, stmt);
|
|
956
|
-
}
|
|
957
|
-
getPropertyNode(storage, propertyName, stmt) {
|
|
958
|
-
let storageMap = this.storagePropertyMap.get(storage);
|
|
959
|
-
let propertyLocal;
|
|
960
|
-
if (!storageMap) {
|
|
961
|
-
storageMap = new Map();
|
|
962
|
-
this.storagePropertyMap.set(storage, storageMap);
|
|
963
|
-
}
|
|
964
|
-
if (storageMap.has(propertyName)) {
|
|
965
|
-
propertyLocal = storageMap.get(propertyName);
|
|
966
|
-
}
|
|
967
|
-
if (propertyLocal) {
|
|
968
|
-
return this.getOrNewPagNode(-1, propertyLocal, stmt);
|
|
969
|
-
}
|
|
970
|
-
return undefined;
|
|
971
|
-
}
|
|
972
|
-
/**
|
|
973
|
-
* add PagEdge
|
|
974
|
-
* @param edgeKind: edge kind differs from API
|
|
975
|
-
* @param propertyNode: PAG node created by protpertyName
|
|
976
|
-
* @param obj: heapObj stored with Storage API
|
|
977
|
-
*/
|
|
978
|
-
addPropertyLinkEdge(propertyNode, storageObj, cid, stmt, edgeKind) {
|
|
979
|
-
if (!(storageObj.getType() instanceof Type_1.ClassType)) {
|
|
980
|
-
return false;
|
|
981
|
-
}
|
|
982
|
-
if (edgeKind === Pag_1.StorageLinkEdgeType.Property2Local) {
|
|
983
|
-
// propertyNode --> objNode
|
|
984
|
-
this.pag.addPagEdge(propertyNode, this.pag.getOrNewNode(cid, storageObj), Pag_1.PagEdgeKind.Copy, stmt);
|
|
985
|
-
}
|
|
986
|
-
else if (edgeKind === Pag_1.StorageLinkEdgeType.Local2Property) {
|
|
987
|
-
// propertyNode <-- objNode
|
|
988
|
-
this.pag.addPagEdge(this.pag.getOrNewNode(cid, storageObj), propertyNode, Pag_1.PagEdgeKind.Copy, stmt);
|
|
989
|
-
}
|
|
990
|
-
else if (edgeKind === Pag_1.StorageLinkEdgeType.TwoWay) {
|
|
991
|
-
// propertyNode <-> objNode
|
|
992
|
-
this.pag.addPagEdge(propertyNode, this.pag.getOrNewNode(cid, storageObj), Pag_1.PagEdgeKind.Copy, stmt);
|
|
993
|
-
this.pag.addPagEdge(this.pag.getOrNewNode(cid, storageObj), propertyNode, Pag_1.PagEdgeKind.Copy, stmt);
|
|
994
|
-
}
|
|
995
|
-
return true;
|
|
996
|
-
}
|
|
997
|
-
/*
|
|
998
|
-
* In ArkIR, ArkField has multiple instances for each stmt which use it
|
|
999
|
-
* But the unique one is needed for pointer analysis
|
|
1000
|
-
* This is a temp solution to use a ArkField->(first instance)
|
|
1001
|
-
* as the unique instance
|
|
1002
|
-
*
|
|
1003
|
-
* node merge condition:
|
|
1004
|
-
* instance field: value and ArkField
|
|
1005
|
-
* static field: ArkField
|
|
1006
|
-
*/
|
|
1007
|
-
getRealInstanceRef(v) {
|
|
1008
|
-
if (!(v instanceof Ref_1.ArkInstanceFieldRef || v instanceof Ref_1.ArkStaticFieldRef)) {
|
|
1009
|
-
return v;
|
|
1010
|
-
}
|
|
1011
|
-
let sig = v.getFieldSignature();
|
|
1012
|
-
let sigStr = sig.toString();
|
|
1013
|
-
let base;
|
|
1014
|
-
let real;
|
|
1015
|
-
if (v instanceof Ref_1.ArkInstanceFieldRef) {
|
|
1016
|
-
base = v.getBase();
|
|
1017
|
-
if (base instanceof Local_1.Local && base.getName() === TSConst_1.GLOBAL_THIS_NAME && base.getDeclaringStmt() == null) {
|
|
1018
|
-
// replace the base in fieldRef
|
|
1019
|
-
base = this.getGlobalThisValue();
|
|
1020
|
-
v.setBase(base);
|
|
1021
|
-
}
|
|
1022
|
-
let key = `${base.getSignature()}-${sigStr}`;
|
|
1023
|
-
real = this.instanceField2UniqInstanceMap.get(key);
|
|
1024
|
-
if (!real) {
|
|
1025
|
-
this.instanceField2UniqInstanceMap.set(key, v);
|
|
1026
|
-
real = v;
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
else {
|
|
1030
|
-
real = this.staticField2UniqInstanceMap.get(sigStr);
|
|
1031
|
-
if (!real) {
|
|
1032
|
-
this.staticField2UniqInstanceMap.set(sigStr, v);
|
|
1033
|
-
real = v;
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
return real;
|
|
1037
|
-
}
|
|
1038
|
-
/**
|
|
1039
|
-
* check if a method is singleton function
|
|
1040
|
-
* rule: static method, assign heap obj to global var or static field, return the receiver
|
|
1041
|
-
*/
|
|
1042
|
-
isSingletonFunction(funcID) {
|
|
1043
|
-
if (this.singletonFuncMap.has(funcID)) {
|
|
1044
|
-
return this.singletonFuncMap.get(funcID);
|
|
1045
|
-
}
|
|
1046
|
-
let arkMethod = this.cg.getArkMethodByFuncID(funcID);
|
|
1047
|
-
if (!arkMethod) {
|
|
1048
|
-
this.singletonFuncMap.set(funcID, false);
|
|
1049
|
-
return false;
|
|
1050
|
-
}
|
|
1051
|
-
if (!arkMethod.isStatic()) {
|
|
1052
|
-
this.singletonFuncMap.set(funcID, false);
|
|
1053
|
-
return false;
|
|
1054
|
-
}
|
|
1055
|
-
let funcPag = this.funcPags.get(funcID);
|
|
1056
|
-
let heapObjects = [...funcPag.getInternalEdges()]
|
|
1057
|
-
.filter(edge => edge.kind === Pag_1.PagEdgeKind.Address)
|
|
1058
|
-
.map(edge => edge.dst);
|
|
1059
|
-
let returnValues = arkMethod.getReturnValues();
|
|
1060
|
-
let result = this.isValueConnected([...funcPag.getInternalEdges()], heapObjects, returnValues);
|
|
1061
|
-
this.singletonFuncMap.set(funcID, result);
|
|
1062
|
-
if (result) {
|
|
1063
|
-
logger.info(`function ${funcID} is marked as singleton function`);
|
|
1064
|
-
}
|
|
1065
|
-
return result;
|
|
1066
|
-
}
|
|
1067
|
-
isValueConnected(edges, leftNodes, targetNodes) {
|
|
1068
|
-
// build funcPag graph
|
|
1069
|
-
const graph = new Map();
|
|
1070
|
-
let hasStaticFieldOrGlobalVar = false;
|
|
1071
|
-
for (const edge of edges) {
|
|
1072
|
-
let dst = this.getRealInstanceRef(edge.dst);
|
|
1073
|
-
let src = this.getRealInstanceRef(edge.src);
|
|
1074
|
-
if (!graph.has(dst)) {
|
|
1075
|
-
graph.set(dst, []);
|
|
1076
|
-
}
|
|
1077
|
-
if (!graph.has(src)) {
|
|
1078
|
-
graph.set(src, []);
|
|
1079
|
-
}
|
|
1080
|
-
if (dst instanceof Ref_1.ArkStaticFieldRef || src instanceof Ref_1.ArkStaticFieldRef) {
|
|
1081
|
-
hasStaticFieldOrGlobalVar = true;
|
|
1082
|
-
}
|
|
1083
|
-
graph.get(src).push(dst);
|
|
1084
|
-
}
|
|
1085
|
-
if (!hasStaticFieldOrGlobalVar) {
|
|
1086
|
-
return false;
|
|
1087
|
-
}
|
|
1088
|
-
for (const targetNode of targetNodes) {
|
|
1089
|
-
for (const leftNode of leftNodes) {
|
|
1090
|
-
const visited = new Set();
|
|
1091
|
-
let meetStaticField = false;
|
|
1092
|
-
if (this.funcPagDfs(graph, visited, leftNode, targetNode, meetStaticField)) {
|
|
1093
|
-
return true; // a value pair that satisfy condition
|
|
1094
|
-
}
|
|
1095
|
-
if (!meetStaticField) {
|
|
1096
|
-
break; // heap obj will not deal any more
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
return false;
|
|
1101
|
-
}
|
|
1102
|
-
funcPagDfs(graph, visited, currentNode, targetNode, staticFieldFound) {
|
|
1103
|
-
if (currentNode === targetNode) {
|
|
1104
|
-
return staticFieldFound;
|
|
1105
|
-
}
|
|
1106
|
-
visited.add(currentNode);
|
|
1107
|
-
for (const neighbor of graph.get(currentNode) || []) {
|
|
1108
|
-
// TODO: add global variable
|
|
1109
|
-
const isSpecialNode = neighbor instanceof Ref_1.ArkStaticFieldRef;
|
|
1110
|
-
if (!visited.has(neighbor)) {
|
|
1111
|
-
if (isSpecialNode) {
|
|
1112
|
-
staticFieldFound = true;
|
|
1113
|
-
}
|
|
1114
|
-
if (this.funcPagDfs(graph, visited, neighbor, targetNode, staticFieldFound)) {
|
|
1115
|
-
return true;
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
return false;
|
|
1120
|
-
}
|
|
1121
|
-
getGlobalThisValue() {
|
|
1122
|
-
return this.globalThisValue;
|
|
1123
|
-
}
|
|
1124
|
-
getEdgeKindForAssignStmt(stmt) {
|
|
1125
|
-
if (this.stmtIsCreateAddressObj(stmt)) {
|
|
1126
|
-
return Pag_1.PagEdgeKind.Address;
|
|
1127
|
-
}
|
|
1128
|
-
if (this.stmtIsCopyKind(stmt)) {
|
|
1129
|
-
return Pag_1.PagEdgeKind.Copy;
|
|
1130
|
-
}
|
|
1131
|
-
if (this.stmtIsReadKind(stmt)) {
|
|
1132
|
-
return Pag_1.PagEdgeKind.Load;
|
|
1133
|
-
}
|
|
1134
|
-
if (this.stmtIsWriteKind(stmt)) {
|
|
1135
|
-
return Pag_1.PagEdgeKind.Write;
|
|
1136
|
-
}
|
|
1137
|
-
return Pag_1.PagEdgeKind.Unknown;
|
|
1138
|
-
}
|
|
1139
|
-
/**
|
|
1140
|
-
* get storageType enum with method's Declaring ClassName
|
|
1141
|
-
*
|
|
1142
|
-
* @param storageName ClassName that method belongs to, currently support AppStorage and SubscribedAbstractProperty
|
|
1143
|
-
* SubscribedAbstractProperty: in following listing, `link1` is infered as ClassType `SubscribedAbstractProperty`,
|
|
1144
|
-
* it needs to get PAG node to check the StorageType
|
|
1145
|
-
* let link1: SubscribedAbstractProperty<A> = AppStorage.link('PropA');
|
|
1146
|
-
* link1.set(a);
|
|
1147
|
-
* @param cs: for search PAG node in SubscribedAbstractProperty
|
|
1148
|
-
* @param cid: for search PAG node in SubscribedAbstractProperty
|
|
1149
|
-
* @returns StorageType enum
|
|
1150
|
-
*/
|
|
1151
|
-
getStorageType(storageName, cs, cid) {
|
|
1152
|
-
switch (storageName) {
|
|
1153
|
-
case 'AppStorage':
|
|
1154
|
-
return Pag_1.StorageType.APP_STORAGE;
|
|
1155
|
-
case 'SubscribedAbstractProperty': {
|
|
1156
|
-
let calleeBaseLocal = cs.callStmt.getInvokeExpr().getBase();
|
|
1157
|
-
let calleeBaseLocalNode = this.pag.getOrNewNode(cid, calleeBaseLocal);
|
|
1158
|
-
if (calleeBaseLocalNode.isStorageLinked()) {
|
|
1159
|
-
let storage = calleeBaseLocalNode.getStorage();
|
|
1160
|
-
return storage.StorageType;
|
|
1161
|
-
}
|
|
1162
|
-
return Pag_1.StorageType.Undefined;
|
|
1163
|
-
}
|
|
1164
|
-
default:
|
|
1165
|
-
return Pag_1.StorageType.Undefined;
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
/**\
|
|
1169
|
-
* ArkNewExpr, ArkNewArrayExpr, function ptr, globalThis
|
|
1170
|
-
*/
|
|
1171
|
-
stmtIsCreateAddressObj(stmt) {
|
|
1172
|
-
let lhOp = stmt.getLeftOp();
|
|
1173
|
-
let rhOp = stmt.getRightOp();
|
|
1174
|
-
if ((rhOp instanceof Expr_1.ArkNewExpr || rhOp instanceof Expr_1.ArkNewArrayExpr) ||
|
|
1175
|
-
(lhOp instanceof Local_1.Local && ((rhOp instanceof Local_1.Local && rhOp.getType() instanceof Type_1.FunctionType &&
|
|
1176
|
-
rhOp.getDeclaringStmt() === null) ||
|
|
1177
|
-
(rhOp instanceof Ref_1.AbstractFieldRef && rhOp.getType() instanceof Type_1.FunctionType))) ||
|
|
1178
|
-
(rhOp instanceof Local_1.Local && rhOp.getName() === TSConst_1.GLOBAL_THIS_NAME && rhOp.getDeclaringStmt() == null)) {
|
|
1179
|
-
return true;
|
|
1180
|
-
}
|
|
1181
|
-
// TODO: add other Address Obj creation
|
|
1182
|
-
// like static object
|
|
1183
|
-
return false;
|
|
1184
|
-
}
|
|
1185
|
-
stmtIsCopyKind(stmt) {
|
|
1186
|
-
let lhOp = stmt.getLeftOp();
|
|
1187
|
-
let rhOp = stmt.getRightOp();
|
|
1188
|
-
let condition = (lhOp instanceof Local_1.Local && (rhOp instanceof Local_1.Local || rhOp instanceof Ref_1.ArkParameterRef ||
|
|
1189
|
-
rhOp instanceof Ref_1.ArkThisRef || rhOp instanceof Ref_1.ArkStaticFieldRef)) ||
|
|
1190
|
-
(lhOp instanceof Ref_1.ArkStaticFieldRef && rhOp instanceof Local_1.Local);
|
|
1191
|
-
if (condition) {
|
|
1192
|
-
return true;
|
|
1193
|
-
}
|
|
1194
|
-
return false;
|
|
1195
|
-
}
|
|
1196
|
-
stmtIsWriteKind(stmt) {
|
|
1197
|
-
let lhOp = stmt.getLeftOp();
|
|
1198
|
-
let rhOp = stmt.getRightOp();
|
|
1199
|
-
if (rhOp instanceof Local_1.Local &&
|
|
1200
|
-
(lhOp instanceof Ref_1.ArkInstanceFieldRef || lhOp instanceof Ref_1.ArkArrayRef)) {
|
|
1201
|
-
return true;
|
|
1202
|
-
}
|
|
1203
|
-
return false;
|
|
1204
|
-
}
|
|
1205
|
-
stmtIsReadKind(stmt) {
|
|
1206
|
-
let lhOp = stmt.getLeftOp();
|
|
1207
|
-
let rhOp = stmt.getRightOp();
|
|
1208
|
-
if (lhOp instanceof Local_1.Local &&
|
|
1209
|
-
(rhOp instanceof Ref_1.ArkInstanceFieldRef || rhOp instanceof Ref_1.ArkArrayRef)) {
|
|
1210
|
-
return true;
|
|
1211
|
-
}
|
|
1212
|
-
return false;
|
|
1213
|
-
}
|
|
1214
|
-
addToDynamicCallSite(funcPag, cs) {
|
|
1215
|
-
var _a;
|
|
1216
|
-
funcPag.addDynamicCallSite(cs);
|
|
1217
|
-
this.pagStat.numDynamicCall++;
|
|
1218
|
-
logger.trace("[add dynamic callsite] " + cs.callStmt.toString() + ": " + ((_a = cs.callStmt.getCfg()) === null || _a === void 0 ? void 0 : _a.getDeclaringMethod().getSignature().toString()));
|
|
1219
|
-
}
|
|
1220
|
-
setPtForNode(node, pts) {
|
|
1221
|
-
if (!pts) {
|
|
1222
|
-
return;
|
|
1223
|
-
}
|
|
1224
|
-
this.pag.getNode(node).setPointTo(pts);
|
|
1225
|
-
}
|
|
1226
|
-
getRealThisLocal(input, funcId) {
|
|
1227
|
-
var _a;
|
|
1228
|
-
if (input.getName() !== 'this')
|
|
1229
|
-
return input;
|
|
1230
|
-
let real = input;
|
|
1231
|
-
let f = this.cg.getArkMethodByFuncID(funcId);
|
|
1232
|
-
(_a = f === null || f === void 0 ? void 0 : f.getCfg()) === null || _a === void 0 ? void 0 : _a.getStmts().forEach(s => {
|
|
1233
|
-
if (s instanceof Stmt_1.ArkAssignStmt && s.getLeftOp() instanceof Local_1.Local) {
|
|
1234
|
-
if (s.getLeftOp().getName() === 'this') {
|
|
1235
|
-
real = s.getLeftOp();
|
|
1236
|
-
return;
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
});
|
|
1240
|
-
return real;
|
|
1241
|
-
}
|
|
1242
|
-
doStat() {
|
|
1243
|
-
this.pagStat.numTotalNode = this.pag.getNodeNum();
|
|
1244
|
-
}
|
|
1245
|
-
printStat() {
|
|
1246
|
-
this.pagStat.printStat();
|
|
1247
|
-
}
|
|
1248
|
-
getStat() {
|
|
1249
|
-
return this.pagStat.getStat();
|
|
1250
|
-
}
|
|
1251
|
-
getUnhandledFuncs() {
|
|
1252
|
-
let handledFuncs = this.getHandledFuncs();
|
|
1253
|
-
let unhandleFuncs = Array.from(this.cg.getNodesIter())
|
|
1254
|
-
.filter(f => !handledFuncs.includes(f.getID()))
|
|
1255
|
-
.map(f => f.getID());
|
|
1256
|
-
return unhandleFuncs;
|
|
1257
|
-
}
|
|
1258
|
-
getHandledFuncs() {
|
|
1259
|
-
return Array.from(this.funcPags.keys());
|
|
1260
|
-
}
|
|
1261
|
-
/**
|
|
1262
|
-
* build export edge in internal func pag
|
|
1263
|
-
* @param value: Value that need to check if it is from import/export
|
|
1264
|
-
* @param originValue: if Value if InstanceFieldRef, the base will be passed to `value` recursively,
|
|
1265
|
-
* fieldRef will be passed to `originValue`
|
|
1266
|
-
*/
|
|
1267
|
-
handleValueFromExternalScope(value, funcID, originValue) {
|
|
1268
|
-
if (value instanceof Local_1.Local) {
|
|
1269
|
-
if (value.getDeclaringStmt()) {
|
|
1270
|
-
// not from external scope
|
|
1271
|
-
return;
|
|
1272
|
-
}
|
|
1273
|
-
if (!value.getType()) {
|
|
1274
|
-
return;
|
|
1275
|
-
}
|
|
1276
|
-
let srcLocal = this.getSourceValueFromExternalScope(value, funcID);
|
|
1277
|
-
if (srcLocal) {
|
|
1278
|
-
// if `value` is from field base, use origin value(fieldRef) instead
|
|
1279
|
-
this.addInterFuncEdge(srcLocal, originValue !== null && originValue !== void 0 ? originValue : value, funcID);
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
else if (value instanceof Ref_1.ArkInstanceFieldRef) {
|
|
1283
|
-
let base = value.getBase();
|
|
1284
|
-
if (base) {
|
|
1285
|
-
this.handleValueFromExternalScope(base, funcID, value);
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
addInterFuncEdge(src, dst, funcID) {
|
|
1290
|
-
var _a, _b, _c;
|
|
1291
|
-
this.interFuncPags = (_a = this.interFuncPags) !== null && _a !== void 0 ? _a : new Map();
|
|
1292
|
-
let interFuncPag = (_b = this.interFuncPags.get(funcID)) !== null && _b !== void 0 ? _b : new Pag_1.InterFuncPag();
|
|
1293
|
-
// Export a local
|
|
1294
|
-
// Add a InterProcedural edge
|
|
1295
|
-
if (dst instanceof Local_1.Local) {
|
|
1296
|
-
let e = { src: src, dst: dst, kind: Pag_1.PagEdgeKind.InterProceduralCopy };
|
|
1297
|
-
interFuncPag.addToInterProceduralEdgeSet(e);
|
|
1298
|
-
this.addExportVariableMap(src, dst);
|
|
1299
|
-
}
|
|
1300
|
-
else if (dst instanceof Ref_1.ArkInstanceFieldRef) {
|
|
1301
|
-
// record the export base use
|
|
1302
|
-
this.addExportVariableMap(src, dst.getBase());
|
|
1303
|
-
}
|
|
1304
|
-
this.interFuncPags.set(funcID, interFuncPag);
|
|
1305
|
-
// Put the function which the src belongs to to worklist
|
|
1306
|
-
let srcFunc = (_c = src.getDeclaringStmt()) === null || _c === void 0 ? void 0 : _c.getCfg().getDeclaringMethod();
|
|
1307
|
-
if (srcFunc) {
|
|
1308
|
-
let srcFuncID = this.cg.getCallGraphNodeByMethod(srcFunc.getSignature()).getID();
|
|
1309
|
-
let cid = this.ctx.getNewContextID(srcFuncID);
|
|
1310
|
-
let csFuncID = new CSFuncID(cid, srcFuncID);
|
|
1311
|
-
this.buildFuncPagAndAddToWorklist(csFuncID);
|
|
1312
|
-
}
|
|
1313
|
-
// Extend other types of src here
|
|
1314
|
-
}
|
|
1315
|
-
getSourceValueFromExternalScope(value, funcID) {
|
|
1316
|
-
let sourceValue;
|
|
1317
|
-
// TODO: first from default method
|
|
1318
|
-
sourceValue = this.getDefaultMethodSourceValue(value, funcID);
|
|
1319
|
-
if (!sourceValue) {
|
|
1320
|
-
sourceValue = this.getExportSourceValue(value, funcID);
|
|
1321
|
-
}
|
|
1322
|
-
return sourceValue;
|
|
1323
|
-
}
|
|
1324
|
-
getDefaultMethodSourceValue(value, funcID) {
|
|
1325
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
1326
|
-
// namespace check
|
|
1327
|
-
let arkMethod = this.cg.getArkMethodByFuncID(funcID);
|
|
1328
|
-
if (!arkMethod) {
|
|
1329
|
-
return;
|
|
1330
|
-
}
|
|
1331
|
-
let declaringNameSpace = arkMethod.getDeclaringArkClass().getDeclaringArkNamespace();
|
|
1332
|
-
while (declaringNameSpace) {
|
|
1333
|
-
let nameSpaceLocals = (_c = (_b = (_a = declaringNameSpace.getDefaultClass()
|
|
1334
|
-
.getDefaultArkMethod()) === null || _a === void 0 ? void 0 : _a.getBody()) === null || _b === void 0 ? void 0 : _b.getLocals()) !== null && _c !== void 0 ? _c : new Map();
|
|
1335
|
-
if (nameSpaceLocals.has(value.getName())) {
|
|
1336
|
-
return nameSpaceLocals.get(value.getName());
|
|
1337
|
-
}
|
|
1338
|
-
declaringNameSpace = (_d = declaringNameSpace.getDeclaringArkNamespace()) !== null && _d !== void 0 ? _d : undefined;
|
|
1339
|
-
}
|
|
1340
|
-
// file check
|
|
1341
|
-
let declaringFile = arkMethod.getDeclaringArkFile();
|
|
1342
|
-
let fileLocals = (_g = (_f = (_e = declaringFile.getDefaultClass()
|
|
1343
|
-
.getDefaultArkMethod()) === null || _e === void 0 ? void 0 : _e.getBody()) === null || _f === void 0 ? void 0 : _f.getLocals()) !== null && _g !== void 0 ? _g : new Map();
|
|
1344
|
-
if (!fileLocals.has(value.getName())) {
|
|
1345
|
-
return;
|
|
1346
|
-
}
|
|
1347
|
-
return fileLocals.get(value.getName());
|
|
1348
|
-
}
|
|
1349
|
-
getExportSourceValue(value, funcID) {
|
|
1350
|
-
let curMethod = this.cg.getArkMethodByFuncID(funcID);
|
|
1351
|
-
if (!curMethod) {
|
|
1352
|
-
return;
|
|
1353
|
-
}
|
|
1354
|
-
let curFile = curMethod.getDeclaringArkFile();
|
|
1355
|
-
let impInfo = curFile.getImportInfoBy(value.getName());
|
|
1356
|
-
if (!impInfo) {
|
|
1357
|
-
return;
|
|
1358
|
-
}
|
|
1359
|
-
let exportSource = impInfo.getLazyExportInfo();
|
|
1360
|
-
if (!exportSource) {
|
|
1361
|
-
return;
|
|
1362
|
-
}
|
|
1363
|
-
let exportSouceValue = exportSource.getArkExport();
|
|
1364
|
-
if (exportSouceValue instanceof Local_1.Local) {
|
|
1365
|
-
return exportSouceValue;
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
addExportVariableMap(src, dst) {
|
|
1369
|
-
var _a;
|
|
1370
|
-
let exportMap = (_a = this.externalScopeVariableMap.get(src)) !== null && _a !== void 0 ? _a : [];
|
|
1371
|
-
if (!exportMap.includes(dst)) {
|
|
1372
|
-
exportMap.push(dst);
|
|
1373
|
-
this.externalScopeVariableMap.set(src, exportMap);
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
getExportVariableMap(src) {
|
|
1377
|
-
var _a;
|
|
1378
|
-
return (_a = this.externalScopeVariableMap.get(src)) !== null && _a !== void 0 ? _a : [];
|
|
1379
|
-
}
|
|
1380
|
-
/// Add inter-procedural Pag Nodes and Edges
|
|
1381
|
-
addEdgesFromInterFuncPag(interFuncPag, cid) {
|
|
1382
|
-
let edges = interFuncPag.getInterProceduralEdges();
|
|
1383
|
-
if (edges.size === 0) {
|
|
1384
|
-
return false;
|
|
1385
|
-
}
|
|
1386
|
-
for (let e of edges) {
|
|
1387
|
-
// Existing local exported nodes -> ExportNode
|
|
1388
|
-
let exportLocal = e.src;
|
|
1389
|
-
let dstPagNode = this.getOrNewPagNode(cid, e.dst);
|
|
1390
|
-
// get export local node in all cid
|
|
1391
|
-
let existingNodes = this.pag.getNodesByValue(exportLocal);
|
|
1392
|
-
existingNodes === null || existingNodes === void 0 ? void 0 : existingNodes.forEach(n => {
|
|
1393
|
-
this.pag.addPagEdge(this.pag.getNode(n), dstPagNode, e.kind);
|
|
1394
|
-
});
|
|
1395
|
-
}
|
|
1396
|
-
return true;
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
exports.PagBuilder = PagBuilder;
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2024-2025 Huawei Device Co., Ltd.
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.PagBuilder = exports.CSFuncID = void 0;
|
|
41
|
+
const CallGraph_1 = require("../model/CallGraph");
|
|
42
|
+
const Stmt_1 = require("../../core/base/Stmt");
|
|
43
|
+
const Expr_1 = require("../../core/base/Expr");
|
|
44
|
+
const Ref_1 = require("../../core/base/Ref");
|
|
45
|
+
const logger_1 = __importStar(require("../../utils/logger"));
|
|
46
|
+
const Local_1 = require("../../core/base/Local");
|
|
47
|
+
const Type_1 = require("../../core/base/Type");
|
|
48
|
+
const Constant_1 = require("../../core/base/Constant");
|
|
49
|
+
const Statistics_1 = require("../common/Statistics");
|
|
50
|
+
const Context_1 = require("./Context");
|
|
51
|
+
const Pag_1 = require("./Pag");
|
|
52
|
+
const TSConst_1 = require("../../core/common/TSConst");
|
|
53
|
+
const Const_1 = require("../../core/common/Const");
|
|
54
|
+
const PTAUtils_1 = require("./PTAUtils");
|
|
55
|
+
const PointerAnalysisConfig_1 = require("./PointerAnalysisConfig");
|
|
56
|
+
const logger = logger_1.default.getLogger(logger_1.LOG_MODULE_TYPE.ARKANALYZER, 'PTA');
|
|
57
|
+
class CSFuncID {
|
|
58
|
+
constructor(cid, fid) {
|
|
59
|
+
this.cid = cid;
|
|
60
|
+
this.funcID = fid;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.CSFuncID = CSFuncID;
|
|
64
|
+
class PagBuilder {
|
|
65
|
+
constructor(p, cg, s, kLimit) {
|
|
66
|
+
this.handledFunc = new Set();
|
|
67
|
+
this.worklist = [];
|
|
68
|
+
// TODO: change string to hash value
|
|
69
|
+
this.staticField2UniqInstanceMap = new Map();
|
|
70
|
+
this.instanceField2UniqInstanceMap = new Map();
|
|
71
|
+
this.cid2ThisRefPtMap = new Map();
|
|
72
|
+
this.cid2ThisRefMap = new Map();
|
|
73
|
+
this.cid2ThisLocalMap = new Map();
|
|
74
|
+
this.sdkMethodReturnValueMap = new Map();
|
|
75
|
+
// record the SDK API param, and create fake Values
|
|
76
|
+
this.sdkMethodParamValueMap = new Map();
|
|
77
|
+
this.fakeSdkMethodParamDeclaringStmt = new Stmt_1.ArkAssignStmt(new Local_1.Local(""), new Local_1.Local(""));
|
|
78
|
+
this.funcHandledThisRound = new Set();
|
|
79
|
+
this.updatedNodesThisRound = new Map();
|
|
80
|
+
this.singletonFuncMap = new Map();
|
|
81
|
+
this.globalThisValue = new Local_1.Local(TSConst_1.GLOBAL_THIS_NAME);
|
|
82
|
+
this.storagePropertyMap = new Map();
|
|
83
|
+
this.externalScopeVariableMap = new Map();
|
|
84
|
+
this.pag = p;
|
|
85
|
+
this.cg = cg;
|
|
86
|
+
this.funcPags = new Map;
|
|
87
|
+
this.ctx = new Context_1.KLimitedContextSensitive(kLimit);
|
|
88
|
+
this.scene = s;
|
|
89
|
+
this.pagStat = new Statistics_1.PAGStat();
|
|
90
|
+
}
|
|
91
|
+
buildFuncPagAndAddToWorklist(cs) {
|
|
92
|
+
if (this.worklist.includes(cs)) {
|
|
93
|
+
return cs;
|
|
94
|
+
}
|
|
95
|
+
this.buildFuncPag(cs.funcID);
|
|
96
|
+
if (this.isSingletonFunction(cs.funcID)) {
|
|
97
|
+
cs.cid = Context_1.DUMMY_CID;
|
|
98
|
+
}
|
|
99
|
+
this.worklist.push(cs);
|
|
100
|
+
return cs;
|
|
101
|
+
}
|
|
102
|
+
addToFuncHandledListThisRound(id) {
|
|
103
|
+
if (this.funcHandledThisRound.has(id)) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
this.funcHandledThisRound.add(id);
|
|
107
|
+
}
|
|
108
|
+
buildForEntries(funcIDs) {
|
|
109
|
+
this.worklist = [];
|
|
110
|
+
funcIDs.forEach(funcID => {
|
|
111
|
+
let cid = this.ctx.getNewContextID(funcID);
|
|
112
|
+
let csFuncID = new CSFuncID(cid, funcID);
|
|
113
|
+
this.buildFuncPagAndAddToWorklist(csFuncID);
|
|
114
|
+
});
|
|
115
|
+
this.handleReachable();
|
|
116
|
+
this.globalThisPagNode = this.getOrNewGlobalThisNode(-1);
|
|
117
|
+
this.pag.addPagEdge(this.globalThisPagNode, this.globalThisPagNode, Pag_1.PagEdgeKind.Copy);
|
|
118
|
+
}
|
|
119
|
+
handleReachable() {
|
|
120
|
+
if (this.worklist.length === 0) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
this.funcHandledThisRound.clear();
|
|
124
|
+
while (this.worklist.length > 0) {
|
|
125
|
+
let csFunc = this.worklist.shift();
|
|
126
|
+
this.buildPagFromFuncPag(csFunc.funcID, csFunc.cid);
|
|
127
|
+
this.addToFuncHandledListThisRound(csFunc.funcID);
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
build() {
|
|
132
|
+
for (let funcID of this.cg.getEntries()) {
|
|
133
|
+
let cid = this.ctx.getNewContextID(funcID);
|
|
134
|
+
let csFuncID = new CSFuncID(cid, funcID);
|
|
135
|
+
this.buildFuncPagAndAddToWorklist(csFuncID);
|
|
136
|
+
this.handleReachable();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
buildFuncPag(funcID) {
|
|
140
|
+
if (this.funcPags.has(funcID)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
let arkMethod = this.cg.getArkMethodByFuncID(funcID);
|
|
144
|
+
if (arkMethod == null) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
let cfg = arkMethod.getCfg();
|
|
148
|
+
if (!cfg) {
|
|
149
|
+
this.buildSDKFuncPag(funcID);
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
logger.trace(`[build FuncPag] ${arkMethod.getSignature().toString()}`);
|
|
153
|
+
let fpag = new Pag_1.FuncPag();
|
|
154
|
+
for (let stmt of cfg.getStmts()) {
|
|
155
|
+
if (stmt instanceof Stmt_1.ArkAssignStmt) {
|
|
156
|
+
stmt.getRightOp().getUses().forEach((v) => {
|
|
157
|
+
this.handleValueFromExternalScope(v, funcID);
|
|
158
|
+
});
|
|
159
|
+
// Add non-call edges
|
|
160
|
+
let kind = this.getEdgeKindForAssignStmt(stmt);
|
|
161
|
+
if (kind !== Pag_1.PagEdgeKind.Unknown) {
|
|
162
|
+
fpag.addInternalEdge(stmt, kind);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
// handle call
|
|
166
|
+
let ivkExpr = stmt.getInvokeExpr();
|
|
167
|
+
if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
|
|
168
|
+
let cs = this.cg.getCallSiteByStmt(stmt);
|
|
169
|
+
if (cs) {
|
|
170
|
+
// direct call is already existing in CG
|
|
171
|
+
// TODO: API Invoke stmt has anonymous method param, how to add these param into callee
|
|
172
|
+
fpag.addNormalCallSite(cs);
|
|
173
|
+
if (ivkExpr.getMethodSignature().getDeclaringClassSignature()
|
|
174
|
+
.getDeclaringFileSignature().getFileName() === Const_1.UNKNOWN_FILE_NAME) {
|
|
175
|
+
fpag.addUnknownCallSite(cs);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
throw new Error('Can not find static callsite');
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr || ivkExpr instanceof Expr_1.ArkPtrInvokeExpr) {
|
|
184
|
+
let ptcs = this.cg.getDynCallsiteByStmt(stmt);
|
|
185
|
+
if (ptcs) {
|
|
186
|
+
this.addToDynamicCallSite(fpag, ptcs);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else if (stmt instanceof Stmt_1.ArkInvokeStmt) {
|
|
191
|
+
// TODO: discuss if we need a invokeStmt
|
|
192
|
+
let cs = this.cg.getCallSiteByStmt(stmt);
|
|
193
|
+
if (cs) {
|
|
194
|
+
// direct call or constructor call is already existing in CG
|
|
195
|
+
// TODO: some ptr invoke stmt is recognized as Static invoke in tests/resources/callgraph/funPtrTest1/fnPtrTest4.ts
|
|
196
|
+
// TODO: instance invoke(ptr invoke)
|
|
197
|
+
if (this.cg.isUnknownMethod(cs.calleeFuncID)) {
|
|
198
|
+
fpag.addUnknownCallSite(cs);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
fpag.addNormalCallSite(cs);
|
|
202
|
+
}
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
let dycs = this.cg.getDynCallsiteByStmt(stmt);
|
|
206
|
+
if (dycs) {
|
|
207
|
+
this.addToDynamicCallSite(fpag, dycs);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
throw new Error('Can not find callsite by stmt');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// TODO: need handle other type of stmt?
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
this.funcPags.set(funcID, fpag);
|
|
218
|
+
this.pagStat.numTotalFunction++;
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* will not create real funcPag, only create param values
|
|
223
|
+
*/
|
|
224
|
+
buildSDKFuncPag(funcID) {
|
|
225
|
+
var _a;
|
|
226
|
+
// check if SDK method
|
|
227
|
+
let cgNode = this.cg.getNode(funcID);
|
|
228
|
+
if (!cgNode.isSdkMethod()) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
let args = (_a = this.cg.getArkMethodByFuncID(funcID)) === null || _a === void 0 ? void 0 : _a.getParameters();
|
|
232
|
+
if (!args) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
let paramArr = [];
|
|
236
|
+
args.forEach((arg) => {
|
|
237
|
+
let argInstance = new Local_1.Local(arg.getName(), arg.getType());
|
|
238
|
+
argInstance.setDeclaringStmt(this.fakeSdkMethodParamDeclaringStmt);
|
|
239
|
+
paramArr.push(argInstance);
|
|
240
|
+
});
|
|
241
|
+
this.sdkMethodParamValueMap.set(funcID, paramArr);
|
|
242
|
+
}
|
|
243
|
+
buildPagFromFuncPag(funcID, cid) {
|
|
244
|
+
var _a;
|
|
245
|
+
let funcPag = this.funcPags.get(funcID);
|
|
246
|
+
if (funcPag === undefined) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (this.handledFunc.has(`${cid}-${funcID}`)) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
this.addEdgesFromFuncPag(funcPag, cid);
|
|
253
|
+
let interFuncPag = (_a = this.interFuncPags) === null || _a === void 0 ? void 0 : _a.get(funcID);
|
|
254
|
+
if (interFuncPag) {
|
|
255
|
+
this.addEdgesFromInterFuncPag(interFuncPag, cid);
|
|
256
|
+
}
|
|
257
|
+
this.addCallsEdgesFromFuncPag(funcPag, cid);
|
|
258
|
+
this.addDynamicCallSite(funcPag, funcID);
|
|
259
|
+
this.addUnknownCallSite(funcPag, funcID);
|
|
260
|
+
this.handledFunc.add(`${cid}-${funcID}`);
|
|
261
|
+
}
|
|
262
|
+
/// Add Pag Nodes and Edges in function
|
|
263
|
+
addEdgesFromFuncPag(funcPag, cid) {
|
|
264
|
+
let inEdges = funcPag.getInternalEdges();
|
|
265
|
+
if (inEdges === undefined) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
for (let e of inEdges) {
|
|
269
|
+
let srcPagNode = this.getOrNewPagNode(cid, e.src, e.stmt);
|
|
270
|
+
let dstPagNode = this.getOrNewPagNode(cid, e.dst, e.stmt);
|
|
271
|
+
this.pag.addPagEdge(srcPagNode, dstPagNode, e.kind, e.stmt);
|
|
272
|
+
// Take place of the real stmt for return
|
|
273
|
+
if (dstPagNode.getStmt() instanceof Stmt_1.ArkReturnStmt) {
|
|
274
|
+
dstPagNode.setStmt(e.stmt);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
/// add Copy edges interprocedural
|
|
280
|
+
addCallsEdgesFromFuncPag(funcPag, cid) {
|
|
281
|
+
for (let cs of funcPag.getNormalCallSites()) {
|
|
282
|
+
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
283
|
+
let calleeCid = this.ctx.getOrNewContext(cid, cs.calleeFuncID, true);
|
|
284
|
+
let calleeCGNode = this.cg.getNode(cs.calleeFuncID);
|
|
285
|
+
// process the Storage API(Static)
|
|
286
|
+
if (!this.processStorage(cs, calleeCGNode, cid)) {
|
|
287
|
+
// If not Storage API, process normal edge
|
|
288
|
+
this.addStaticPagCallEdge(cs, cid, calleeCid);
|
|
289
|
+
}
|
|
290
|
+
// Add edge to thisRef for special calls
|
|
291
|
+
if (calleeCGNode.getKind() === CallGraph_1.CallGraphNodeKind.constructor ||
|
|
292
|
+
calleeCGNode.getKind() === CallGraph_1.CallGraphNodeKind.intrinsic) {
|
|
293
|
+
let callee = this.scene.getMethod(this.cg.getMethodByFuncID(cs.calleeFuncID));
|
|
294
|
+
if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
295
|
+
let baseNode = this.getOrNewPagNode(cid, ivkExpr.getBase());
|
|
296
|
+
let baseNodeID = baseNode.getID();
|
|
297
|
+
this.addThisRefCallEdge(baseNodeID, cid, ivkExpr, callee, calleeCid, cs.callerFuncID);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
logger.error(`constructor or intrinsic func is static ${ivkExpr.toString()}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* process Storage API
|
|
308
|
+
* @returns boolean: check if the cs represent a Storage API, no matter the API will success or fail
|
|
309
|
+
*/
|
|
310
|
+
processStorage(cs, calleeCGNode, cid) {
|
|
311
|
+
let storageName = calleeCGNode.getMethod().getDeclaringClassSignature().getClassName();
|
|
312
|
+
let storageType = this.getStorageType(storageName, cs, cid);
|
|
313
|
+
// TODO: add other storages
|
|
314
|
+
if (storageType === Pag_1.StorageType.APP_STORAGE) {
|
|
315
|
+
let calleeName = calleeCGNode.getMethod().getMethodSubSignature().getMethodName();
|
|
316
|
+
// TODO: complete AppStorage API
|
|
317
|
+
if (calleeName === 'setOrCreate') {
|
|
318
|
+
this.processStorageSetOrCreate(cs, cid);
|
|
319
|
+
}
|
|
320
|
+
else if (calleeName === 'link') {
|
|
321
|
+
this.processStorageLink(cs, cid);
|
|
322
|
+
}
|
|
323
|
+
else if (calleeName === 'prop') {
|
|
324
|
+
this.processStorageProp(cs, cid);
|
|
325
|
+
}
|
|
326
|
+
else if (calleeName === 'set') {
|
|
327
|
+
this.processStorageSet(cs, cid);
|
|
328
|
+
}
|
|
329
|
+
else if (calleeName === 'get') {
|
|
330
|
+
this.processStorageGet(cs, cid);
|
|
331
|
+
}
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
else if (storageType === Pag_1.StorageType.LOCAL_STORAGE) {
|
|
335
|
+
// TODO: LocalStorage is not Static
|
|
336
|
+
}
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
processStorageSetOrCreate(cs, cid) {
|
|
340
|
+
let propertyStr = this.getPropertyName(cs.args[0]);
|
|
341
|
+
if (!propertyStr) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
let propertyName = propertyStr;
|
|
345
|
+
let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
|
|
346
|
+
let storageObj = cs.args[1];
|
|
347
|
+
this.addPropertyLinkEdge(propertyNode, storageObj, cid, cs.callStmt, Pag_1.StorageLinkEdgeType.Local2Property);
|
|
348
|
+
}
|
|
349
|
+
processStorageLink(cs, cid) {
|
|
350
|
+
let propertyStr = this.getPropertyName(cs.args[0]);
|
|
351
|
+
if (!propertyStr) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
let propertyName = propertyStr;
|
|
355
|
+
let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
|
|
356
|
+
let leftOp = cs.callStmt.getLeftOp();
|
|
357
|
+
let linkedOpNode = this.pag.getOrNewNode(cid, leftOp);
|
|
358
|
+
if (linkedOpNode instanceof Pag_1.PagLocalNode) {
|
|
359
|
+
linkedOpNode.setStorageLink(Pag_1.StorageType.APP_STORAGE, propertyName);
|
|
360
|
+
}
|
|
361
|
+
this.pag.addPagEdge(propertyNode, linkedOpNode, Pag_1.PagEdgeKind.Copy);
|
|
362
|
+
this.pag.addPagEdge(linkedOpNode, propertyNode, Pag_1.PagEdgeKind.Copy);
|
|
363
|
+
}
|
|
364
|
+
processStorageProp(cs, cid) {
|
|
365
|
+
let propertyStr = this.getPropertyName(cs.args[0]);
|
|
366
|
+
if (!propertyStr) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
let propertyName = propertyStr;
|
|
370
|
+
let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
|
|
371
|
+
let leftOp = cs.callStmt.getLeftOp();
|
|
372
|
+
let linkedOpNode = this.pag.getOrNewNode(cid, leftOp);
|
|
373
|
+
if (linkedOpNode instanceof Pag_1.PagLocalNode) {
|
|
374
|
+
linkedOpNode.setStorageLink(Pag_1.StorageType.APP_STORAGE, propertyName);
|
|
375
|
+
}
|
|
376
|
+
this.pag.addPagEdge(propertyNode, linkedOpNode, Pag_1.PagEdgeKind.Copy);
|
|
377
|
+
}
|
|
378
|
+
processStorageSet(cs, cid) {
|
|
379
|
+
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
380
|
+
if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
381
|
+
let base = ivkExpr.getBase();
|
|
382
|
+
let baseNode = this.pag.getOrNewNode(cid, base);
|
|
383
|
+
if (baseNode.isStorageLinked()) {
|
|
384
|
+
let argsNode = this.pag.getOrNewNode(cid, cs.args[0]);
|
|
385
|
+
this.pag.addPagEdge(argsNode, baseNode, Pag_1.PagEdgeKind.Copy);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
else if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
|
|
389
|
+
// TODO: process AppStorage.set()
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
processStorageGet(cs, cid) {
|
|
393
|
+
if (!(cs.callStmt instanceof Stmt_1.ArkAssignStmt)) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
let leftOp = cs.callStmt.getLeftOp();
|
|
397
|
+
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
398
|
+
let propertyName;
|
|
399
|
+
if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
|
|
400
|
+
let propertyStr = this.getPropertyName(cs.args[0]);
|
|
401
|
+
if (propertyStr) {
|
|
402
|
+
propertyName = propertyStr;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
else if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
406
|
+
let baseNode = this.pag.getOrNewNode(cid, ivkExpr.getBase());
|
|
407
|
+
if (baseNode.isStorageLinked()) {
|
|
408
|
+
propertyName = baseNode.getStorage().PropertyName;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
let propertyNode = this.getPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
|
|
412
|
+
if (!propertyNode) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
this.pag.addPagEdge(propertyNode, this.pag.getOrNewNode(cid, leftOp, cs.callStmt), Pag_1.PagEdgeKind.Copy, cs.callStmt);
|
|
416
|
+
}
|
|
417
|
+
getPropertyName(value) {
|
|
418
|
+
if (value instanceof Local_1.Local) {
|
|
419
|
+
let type = value.getType();
|
|
420
|
+
if (type instanceof Type_1.StringType) {
|
|
421
|
+
return type.getName();
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
else if (value instanceof Constant_1.Constant) {
|
|
425
|
+
return value.getValue();
|
|
426
|
+
}
|
|
427
|
+
return undefined;
|
|
428
|
+
}
|
|
429
|
+
addDynamicCallSite(funcPag, funcID) {
|
|
430
|
+
// add dyn callsite in funcpag to base node
|
|
431
|
+
for (let cs of funcPag.getDynamicCallSites()) {
|
|
432
|
+
let invokeExpr = cs.callStmt.getInvokeExpr();
|
|
433
|
+
let base;
|
|
434
|
+
if (invokeExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
435
|
+
base = invokeExpr.getBase();
|
|
436
|
+
}
|
|
437
|
+
else if (invokeExpr instanceof Expr_1.ArkPtrInvokeExpr) {
|
|
438
|
+
base = invokeExpr.getFuncPtrLocal();
|
|
439
|
+
}
|
|
440
|
+
// TODO: check base under different cid
|
|
441
|
+
let baseNodeIDs = this.pag.getNodesByValue(base);
|
|
442
|
+
if (!baseNodeIDs) {
|
|
443
|
+
// bind the call site to export base
|
|
444
|
+
let interProceduralLocal = this.getSourceValueFromExternalScope(base, funcID);
|
|
445
|
+
if (interProceduralLocal) {
|
|
446
|
+
baseNodeIDs = this.pag.getNodesByValue(interProceduralLocal);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (!baseNodeIDs) {
|
|
450
|
+
logger.warn(`[build dynamic call site] can not handle call site with base ${base.toString()}`);
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
for (let nodeID of baseNodeIDs.values()) {
|
|
454
|
+
let node = this.pag.getNode(nodeID);
|
|
455
|
+
if (!(node instanceof Pag_1.PagLocalNode)) {
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
node.addRelatedDynCallSite(cs);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
addUnknownCallSite(funcPag, funcID) {
|
|
463
|
+
var _a;
|
|
464
|
+
let method = this.cg.getArkMethodByFuncID(funcID);
|
|
465
|
+
if (!method) {
|
|
466
|
+
throw new Error(`can not find ArkMethod by FuncID ${funcID}`);
|
|
467
|
+
}
|
|
468
|
+
let locals = (_a = method.getBody()) === null || _a === void 0 ? void 0 : _a.getLocals();
|
|
469
|
+
funcPag.getUnknownCallSites().forEach((unknownCallSite) => {
|
|
470
|
+
var _a;
|
|
471
|
+
let calleeName = (_a = unknownCallSite.callStmt.getInvokeExpr()) === null || _a === void 0 ? void 0 : _a.getMethodSignature().getMethodSubSignature().getMethodName();
|
|
472
|
+
let base = locals.get(calleeName);
|
|
473
|
+
if (base) {
|
|
474
|
+
let baseNodeIDs = this.pag.getNodesByValue(base);
|
|
475
|
+
if (!baseNodeIDs) {
|
|
476
|
+
logger.warn(`[build dynamic call site] can not handle call site with base ${base.toString()}`);
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
for (let nodeID of baseNodeIDs.values()) {
|
|
480
|
+
let node = this.pag.getNode(nodeID);
|
|
481
|
+
if (!(node instanceof Pag_1.PagLocalNode)) {
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
node.addRelatedUnknownCallSite(unknownCallSite);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
addDynamicCallEdge(cs, baseClassPTNode, cid) {
|
|
490
|
+
let srcNodes = [];
|
|
491
|
+
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
492
|
+
let ptNode = this.pag.getNode(baseClassPTNode);
|
|
493
|
+
let value = ptNode.getValue();
|
|
494
|
+
let callees = this.getDynamicCallee(ptNode, value, ivkExpr, cs);
|
|
495
|
+
for (let callee of callees) {
|
|
496
|
+
if (!callee) {
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
// get caller and callee CG node, add param and return value PAG edge
|
|
500
|
+
let dstCGNode = this.cg.getCallGraphNodeByMethod(callee.getSignature());
|
|
501
|
+
let callerNode = this.cg.getNode(cs.callerFuncID);
|
|
502
|
+
if (!callerNode) {
|
|
503
|
+
throw new Error("Can not get caller method node");
|
|
504
|
+
}
|
|
505
|
+
// update call graph
|
|
506
|
+
// TODO: movo to cgbuilder
|
|
507
|
+
this.cg.addDynamicCallEdge(callerNode.getID(), dstCGNode.getID(), cs.callStmt);
|
|
508
|
+
if (!this.cg.detectReachable(dstCGNode.getID(), callerNode.getID())) {
|
|
509
|
+
let calleeCid = this.ctx.getOrNewContext(cid, dstCGNode.getID(), true);
|
|
510
|
+
let staticCS = new CallGraph_1.CallSite(cs.callStmt, cs.args, dstCGNode.getID(), cs.callerFuncID);
|
|
511
|
+
srcNodes.push(...this.processContainerPagCallEdge(staticCS, cid, baseClassPTNode));
|
|
512
|
+
srcNodes.push(...this.addStaticPagCallEdge(staticCS, cid, calleeCid));
|
|
513
|
+
// Pass base's pts to callee's this pointer
|
|
514
|
+
if (!dstCGNode.isSdkMethod() && ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
515
|
+
let srcBaseNode = this.addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, cs.callerFuncID);
|
|
516
|
+
srcNodes.push(srcBaseNode);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return srcNodes;
|
|
521
|
+
}
|
|
522
|
+
getDynamicCallee(ptNode, value, ivkExpr, cs) {
|
|
523
|
+
let callee = [];
|
|
524
|
+
if (ptNode instanceof Pag_1.PagFuncNode) {
|
|
525
|
+
// function ptr invoke
|
|
526
|
+
let tempCallee = this.scene.getMethod(ptNode.getMethod());
|
|
527
|
+
if (!callee) {
|
|
528
|
+
return callee;
|
|
529
|
+
}
|
|
530
|
+
callee.push(tempCallee);
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
let calleeName = ivkExpr.getMethodSignature().getMethodSubSignature().getMethodName();
|
|
534
|
+
// instance method invoke
|
|
535
|
+
if (!(value instanceof Expr_1.ArkNewExpr || value instanceof Expr_1.ArkNewArrayExpr)) {
|
|
536
|
+
return callee;
|
|
537
|
+
}
|
|
538
|
+
let tempCallee;
|
|
539
|
+
// try to get callee by MethodSignature
|
|
540
|
+
if (value instanceof Expr_1.ArkNewExpr) {
|
|
541
|
+
// get class signature
|
|
542
|
+
let clsSig = value.getType().getClassSignature();
|
|
543
|
+
let cls;
|
|
544
|
+
cls = this.scene.getClass(clsSig);
|
|
545
|
+
while (!tempCallee && cls) {
|
|
546
|
+
tempCallee = cls.getMethodWithName(calleeName);
|
|
547
|
+
cls = cls.getSuperClass();
|
|
548
|
+
}
|
|
549
|
+
if (!tempCallee) {
|
|
550
|
+
tempCallee = this.scene.getMethod(ivkExpr.getMethodSignature());
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
if (!tempCallee && cs.args) {
|
|
554
|
+
// while pts has {o_1, o_2} and invoke expr represents a method that only {o_1} has
|
|
555
|
+
// return empty node when {o_2} come in
|
|
556
|
+
// try to get callee by anonymous method in param
|
|
557
|
+
for (let arg of cs.args) {
|
|
558
|
+
// TODO: anonymous method param and return value pointer pass
|
|
559
|
+
let argType = arg.getType();
|
|
560
|
+
if (argType instanceof Type_1.FunctionType) {
|
|
561
|
+
callee.push(this.scene.getMethod(argType.getMethodSignature()));
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
else if (tempCallee) {
|
|
566
|
+
callee.push(tempCallee);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
return callee;
|
|
570
|
+
}
|
|
571
|
+
addUpdatedNode(nodeID, diffPT) {
|
|
572
|
+
var _a;
|
|
573
|
+
let ptaConfig = PointerAnalysisConfig_1.PointerAnalysisConfig.getInstance();
|
|
574
|
+
let updatedNode = (_a = this.updatedNodesThisRound.get(nodeID)) !== null && _a !== void 0 ? _a : new ptaConfig.ptsCollectionCtor();
|
|
575
|
+
updatedNode.union(diffPT);
|
|
576
|
+
this.updatedNodesThisRound.set(nodeID, updatedNode);
|
|
577
|
+
}
|
|
578
|
+
getUpdatedNodes() {
|
|
579
|
+
return this.updatedNodesThisRound;
|
|
580
|
+
}
|
|
581
|
+
resetUpdatedNodes() {
|
|
582
|
+
this.updatedNodesThisRound.clear();
|
|
583
|
+
}
|
|
584
|
+
handleUnkownDynamicCall(cs, cid) {
|
|
585
|
+
var _a;
|
|
586
|
+
let srcNodes = [];
|
|
587
|
+
let callerNode = this.cg.getNode(cs.callerFuncID);
|
|
588
|
+
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
589
|
+
logger.warn("Handling unknown dyn call site : \n " + callerNode.getMethod().toString()
|
|
590
|
+
+ '\n --> ' + ivkExpr.toString() + '\n CID: ' + cid);
|
|
591
|
+
let callees = [];
|
|
592
|
+
let callee = null;
|
|
593
|
+
callee = this.scene.getMethod(ivkExpr.getMethodSignature());
|
|
594
|
+
if (!callee) {
|
|
595
|
+
(_a = cs.args) === null || _a === void 0 ? void 0 : _a.forEach(arg => {
|
|
596
|
+
if (arg.getType() instanceof Type_1.FunctionType) {
|
|
597
|
+
callee = this.scene.getMethod(arg.getType().getMethodSignature());
|
|
598
|
+
if (callee) {
|
|
599
|
+
callees.push(callee);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
callees.push(callee);
|
|
606
|
+
}
|
|
607
|
+
if (callees.length === 0) {
|
|
608
|
+
return srcNodes;
|
|
609
|
+
}
|
|
610
|
+
callees.forEach(callee => {
|
|
611
|
+
let dstCGNode = this.cg.getCallGraphNodeByMethod(callee.getSignature());
|
|
612
|
+
if (!callerNode) {
|
|
613
|
+
throw new Error("Can not get caller method node");
|
|
614
|
+
}
|
|
615
|
+
if (this.processStorage(cs, dstCGNode, cid)) {
|
|
616
|
+
if (ivkExpr.getArgs().length !== 0) {
|
|
617
|
+
// for AppStorage.set() instance invoke, add obj to reanalyze list
|
|
618
|
+
let argsNode = this.pag.getOrNewNode(cid, cs.args[0]);
|
|
619
|
+
srcNodes.push(argsNode.getID());
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
logger.warn(`\tAdd call edge of unknown call ${callee.getSignature().toString()}`);
|
|
623
|
+
this.cg.addDynamicCallEdge(callerNode.getID(), dstCGNode.getID(), cs.callStmt);
|
|
624
|
+
if (!this.cg.detectReachable(dstCGNode.getID(), callerNode.getID())) {
|
|
625
|
+
let calleeCid = this.ctx.getOrNewContext(cid, dstCGNode.getID(), true);
|
|
626
|
+
let staticCS = new CallGraph_1.CallSite(cs.callStmt, cs.args, dstCGNode.getID(), cs.callerFuncID);
|
|
627
|
+
let staticSrcNodes = this.addStaticPagCallEdge(staticCS, cid, calleeCid);
|
|
628
|
+
srcNodes.push(...staticSrcNodes);
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
return srcNodes;
|
|
632
|
+
}
|
|
633
|
+
handleUnprocessedCallSites(processedCallSites) {
|
|
634
|
+
let reAnalyzeNodes = [];
|
|
635
|
+
for (let funcID of this.funcHandledThisRound) {
|
|
636
|
+
let funcPag = this.funcPags.get(funcID);
|
|
637
|
+
if (!funcPag) {
|
|
638
|
+
logger.error(`can not find funcPag of handled func ${funcID}`);
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
let callSites = funcPag.getDynamicCallSites();
|
|
642
|
+
const diffCallSites = new Set(Array.from(callSites).filter(item => !processedCallSites.has(item)));
|
|
643
|
+
diffCallSites.forEach((cs) => {
|
|
644
|
+
let ivkExpr = cs.callStmt.getInvokeExpr();
|
|
645
|
+
if (!(ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr)) {
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
// Get local of base class
|
|
649
|
+
let base = ivkExpr.getBase();
|
|
650
|
+
// TODO: remove this after multiple this local fixed
|
|
651
|
+
base = this.getRealThisLocal(base, cs.callerFuncID);
|
|
652
|
+
// Get PAG nodes for this base's local
|
|
653
|
+
let ctx2NdMap = this.pag.getNodesByValue(base);
|
|
654
|
+
if (!ctx2NdMap) {
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
for (let [cid] of ctx2NdMap.entries()) {
|
|
658
|
+
reAnalyzeNodes.push(...this.handleUnkownDynamicCall(cs, cid));
|
|
659
|
+
}
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
return reAnalyzeNodes;
|
|
663
|
+
}
|
|
664
|
+
addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, callerFunID) {
|
|
665
|
+
var _a;
|
|
666
|
+
if (!callee || !callee.getCfg()) {
|
|
667
|
+
logger.error(`callee is null`);
|
|
668
|
+
return -1;
|
|
669
|
+
}
|
|
670
|
+
let thisAssignStmt = (_a = callee.getCfg()) === null || _a === void 0 ? void 0 : _a.getStmts().filter(s => s instanceof Stmt_1.ArkAssignStmt && s.getRightOp() instanceof Ref_1.ArkThisRef);
|
|
671
|
+
let thisPtr = (thisAssignStmt === null || thisAssignStmt === void 0 ? void 0 : thisAssignStmt.at(0)).getRightOp();
|
|
672
|
+
if (!thisPtr) {
|
|
673
|
+
throw new Error('Can not get this ptr');
|
|
674
|
+
}
|
|
675
|
+
// IMPORTANT: set cid 2 base Pt info firstly
|
|
676
|
+
this.cid2ThisRefPtMap.set(calleeCid, baseClassPTNode);
|
|
677
|
+
let thisRefNode = this.getOrNewThisRefNode(calleeCid, thisPtr);
|
|
678
|
+
thisRefNode.addPTNode(baseClassPTNode);
|
|
679
|
+
let srcBaseLocal = ivkExpr.getBase();
|
|
680
|
+
srcBaseLocal = this.getRealThisLocal(srcBaseLocal, callerFunID);
|
|
681
|
+
let srcNodeId = this.pag.hasCtxNode(cid, srcBaseLocal);
|
|
682
|
+
if (!srcNodeId) {
|
|
683
|
+
// this check is for export local and closure use
|
|
684
|
+
// replace the invoke base, because its origin base has no pag node
|
|
685
|
+
let interProceduralLocal = this.getSourceValueFromExternalScope(srcBaseLocal, callerFunID);
|
|
686
|
+
if (interProceduralLocal) {
|
|
687
|
+
srcNodeId = this.pag.hasCtxNode(cid, interProceduralLocal);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
if (!srcNodeId) {
|
|
691
|
+
throw new Error('Can not get base node');
|
|
692
|
+
}
|
|
693
|
+
this.pag.addPagEdge(this.pag.getNode(srcNodeId), thisRefNode, Pag_1.PagEdgeKind.This);
|
|
694
|
+
return srcNodeId;
|
|
695
|
+
}
|
|
696
|
+
/*
|
|
697
|
+
* Add copy edges from arguments to parameters
|
|
698
|
+
* ret edges from return values to callsite
|
|
699
|
+
* Return src node
|
|
700
|
+
*/
|
|
701
|
+
addStaticPagCallEdge(cs, callerCid, calleeCid) {
|
|
702
|
+
var _a, _b;
|
|
703
|
+
if (!calleeCid) {
|
|
704
|
+
calleeCid = this.ctx.getOrNewContext(callerCid, cs.calleeFuncID, true);
|
|
705
|
+
}
|
|
706
|
+
let srcNodes = [];
|
|
707
|
+
// Add reachable
|
|
708
|
+
let calleeNode = this.cg.getNode(cs.calleeFuncID);
|
|
709
|
+
let calleeMethod = this.scene.getMethod(calleeNode.getMethod());
|
|
710
|
+
if (!calleeMethod) {
|
|
711
|
+
// TODO: check if nodes need to delete
|
|
712
|
+
return srcNodes;
|
|
713
|
+
}
|
|
714
|
+
if (calleeNode.isSdkMethod()) {
|
|
715
|
+
srcNodes.push(...this.addSDKMethodPagCallEdge(cs, callerCid, calleeCid));
|
|
716
|
+
return srcNodes;
|
|
717
|
+
}
|
|
718
|
+
if (!calleeMethod.getCfg()) {
|
|
719
|
+
// method have no cfg body
|
|
720
|
+
return srcNodes;
|
|
721
|
+
}
|
|
722
|
+
let calleeCS = this.buildFuncPagAndAddToWorklist(new CSFuncID(calleeCid, cs.calleeFuncID));
|
|
723
|
+
// callee cid will updated if callee is singleton
|
|
724
|
+
calleeCid = calleeCS.cid;
|
|
725
|
+
// TODO: getParameterInstances's performance is not good. Need to refactor
|
|
726
|
+
let params = calleeMethod.getCfg().getStmts()
|
|
727
|
+
.filter(stmt => stmt instanceof Stmt_1.ArkAssignStmt && stmt.getRightOp() instanceof Ref_1.ArkParameterRef)
|
|
728
|
+
.map(stmt => stmt.getRightOp());
|
|
729
|
+
let argNum = (_a = cs.args) === null || _a === void 0 ? void 0 : _a.length;
|
|
730
|
+
if (argNum) {
|
|
731
|
+
// add args to parameters edges
|
|
732
|
+
for (let i = 0; i < argNum; i++) {
|
|
733
|
+
let arg = (_b = cs.args) === null || _b === void 0 ? void 0 : _b.at(i);
|
|
734
|
+
let param = params.at(i);
|
|
735
|
+
// TODO: param type should be ArkParameterRef?
|
|
736
|
+
if (arg && param) {
|
|
737
|
+
if (arg instanceof Constant_1.Constant) {
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
if (arg instanceof Expr_1.AbstractExpr) {
|
|
741
|
+
// TODO: handle this
|
|
742
|
+
continue;
|
|
743
|
+
}
|
|
744
|
+
// Get or create new PAG node for argument and parameter
|
|
745
|
+
let srcPagNode = this.getOrNewPagNode(callerCid, arg, cs.callStmt);
|
|
746
|
+
let dstPagNode = this.getOrNewPagNode(calleeCid, param, cs.callStmt);
|
|
747
|
+
this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
|
|
748
|
+
srcNodes.push(srcPagNode.getID());
|
|
749
|
+
}
|
|
750
|
+
// TODO: handle other types of parmeters
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
// add ret to caller edges
|
|
754
|
+
let retStmts = calleeMethod.getReturnStmt();
|
|
755
|
+
// TODO: call statement must be a assignment state
|
|
756
|
+
if (cs.callStmt instanceof Stmt_1.ArkAssignStmt) {
|
|
757
|
+
let retDst = cs.callStmt.getLeftOp();
|
|
758
|
+
for (let retStmt of retStmts) {
|
|
759
|
+
let retValue = retStmt.getOp();
|
|
760
|
+
if (retValue instanceof Local_1.Local) {
|
|
761
|
+
let srcPagNode = this.getOrNewPagNode(calleeCid, retValue, retStmt);
|
|
762
|
+
let dstPagNode = this.getOrNewPagNode(callerCid, retDst, cs.callStmt);
|
|
763
|
+
this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, retStmt);
|
|
764
|
+
}
|
|
765
|
+
else if (retValue instanceof Constant_1.Constant) {
|
|
766
|
+
continue;
|
|
767
|
+
}
|
|
768
|
+
else if (retValue instanceof Expr_1.AbstractExpr) {
|
|
769
|
+
logger.debug(retValue);
|
|
770
|
+
continue;
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
throw new Error('return dst not a local or constant, but: ' + retValue.getType().toString());
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return srcNodes;
|
|
778
|
+
}
|
|
779
|
+
addSDKMethodPagCallEdge(cs, callerCid, calleeCid) {
|
|
780
|
+
let srcNodes = [];
|
|
781
|
+
let calleeNode = this.cg.getNode(cs.calleeFuncID);
|
|
782
|
+
let calleeMethod = this.scene.getMethod(calleeNode.getMethod());
|
|
783
|
+
if (!calleeMethod) {
|
|
784
|
+
return srcNodes;
|
|
785
|
+
}
|
|
786
|
+
// block the container SDK
|
|
787
|
+
if ((0, PTAUtils_1.IsCollectionAPI)(calleeMethod.getSignature())) {
|
|
788
|
+
return srcNodes;
|
|
789
|
+
}
|
|
790
|
+
if (!this.sdkMethodParamValueMap.has(calleeNode.getID())) {
|
|
791
|
+
this.buildSDKFuncPag(calleeNode.getID());
|
|
792
|
+
}
|
|
793
|
+
this.addSDKMethodReturnPagEdge(cs, callerCid, calleeCid, calleeMethod);
|
|
794
|
+
srcNodes.push(...this.addSDKMethodParamPagEdge(cs, callerCid, calleeCid, calleeNode.getID()));
|
|
795
|
+
return srcNodes;
|
|
796
|
+
}
|
|
797
|
+
addSDKMethodReturnPagEdge(cs, callerCid, calleeCid, calleeMethod) {
|
|
798
|
+
let returnType = calleeMethod.getReturnType();
|
|
799
|
+
if (!(returnType instanceof Type_1.ClassType) || !(cs.callStmt instanceof Stmt_1.ArkAssignStmt)) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
// check fake heap object exists or not
|
|
803
|
+
let cidMap = this.sdkMethodReturnValueMap.get(calleeMethod);
|
|
804
|
+
if (!cidMap) {
|
|
805
|
+
cidMap = new Map();
|
|
806
|
+
}
|
|
807
|
+
let newExpr = cidMap.get(calleeCid);
|
|
808
|
+
if (!newExpr) {
|
|
809
|
+
if (returnType instanceof Type_1.ClassType) {
|
|
810
|
+
newExpr = new Expr_1.ArkNewExpr(returnType);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
cidMap.set(calleeCid, newExpr);
|
|
814
|
+
this.sdkMethodReturnValueMap.set(calleeMethod, cidMap);
|
|
815
|
+
let srcPagNode = this.getOrNewPagNode(calleeCid, newExpr);
|
|
816
|
+
let dstPagNode = this.getOrNewPagNode(callerCid, cs.callStmt.getLeftOp(), cs.callStmt);
|
|
817
|
+
this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Address, cs.callStmt);
|
|
818
|
+
}
|
|
819
|
+
addSDKMethodParamPagEdge(cs, callerCid, calleeCid, funcID) {
|
|
820
|
+
var _a, _b;
|
|
821
|
+
let argNum = (_a = cs.args) === null || _a === void 0 ? void 0 : _a.length;
|
|
822
|
+
let srcNodes = [];
|
|
823
|
+
if (argNum) {
|
|
824
|
+
// add args to parameters edges
|
|
825
|
+
for (let i = 0; i < argNum; i++) {
|
|
826
|
+
let arg = (_b = cs.args) === null || _b === void 0 ? void 0 : _b.at(i);
|
|
827
|
+
let paramValue;
|
|
828
|
+
if (arg instanceof Local_1.Local && arg.getType() instanceof Type_1.FunctionType) {
|
|
829
|
+
// TODO: cannot find value
|
|
830
|
+
paramValue = this.sdkMethodParamValueMap.get(funcID)[i];
|
|
831
|
+
}
|
|
832
|
+
else {
|
|
833
|
+
continue;
|
|
834
|
+
}
|
|
835
|
+
if (arg && paramValue) {
|
|
836
|
+
// Get or create new PAG node for argument and parameter
|
|
837
|
+
let srcPagNode = this.getOrNewPagNode(callerCid, arg, cs.callStmt);
|
|
838
|
+
let dstPagNode = this.getOrNewPagNode(calleeCid, paramValue, cs.callStmt);
|
|
839
|
+
if (dstPagNode instanceof Pag_1.PagLocalNode) {
|
|
840
|
+
// set the fake param Value in PagLocalNode
|
|
841
|
+
/**
|
|
842
|
+
* TODO: !!!
|
|
843
|
+
* some API param is in the form of anonymous method:
|
|
844
|
+
* component/common.d.ts
|
|
845
|
+
* declare function animateTo(value: AnimateParam, event: () => void): void;
|
|
846
|
+
*
|
|
847
|
+
* this param fake Value will create PagFuncNode rather than PagLocalNode
|
|
848
|
+
* when this API is called, the anonymous method pointer will not be able to pass into the fake Value PagNode
|
|
849
|
+
*/
|
|
850
|
+
dstPagNode.setSdkParam();
|
|
851
|
+
let sdkParamInvokeStmt = new Stmt_1.ArkInvokeStmt(new Expr_1.ArkPtrInvokeExpr(arg.getType().getMethodSignature(), paramValue, []));
|
|
852
|
+
// create new DynCallSite
|
|
853
|
+
let sdkParamCallSite = new CallGraph_1.DynCallSite(funcID, sdkParamInvokeStmt, undefined, undefined);
|
|
854
|
+
dstPagNode.addRelatedDynCallSite(sdkParamCallSite);
|
|
855
|
+
}
|
|
856
|
+
this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
|
|
857
|
+
srcNodes.push(srcPagNode.getID());
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
return srcNodes;
|
|
862
|
+
}
|
|
863
|
+
processContainerPagCallEdge(cs, cid, baseClassPTNode) {
|
|
864
|
+
let srcNodes = [];
|
|
865
|
+
let calleeNode = this.cg.getNode(cs.calleeFuncID);
|
|
866
|
+
let calleeMethod = this.scene.getMethod(calleeNode.getMethod());
|
|
867
|
+
let ptNode = this.pag.getNode(baseClassPTNode);
|
|
868
|
+
if (!calleeMethod || !(ptNode instanceof Pag_1.PagNewContainerExprNode)) {
|
|
869
|
+
return srcNodes;
|
|
870
|
+
}
|
|
871
|
+
let containerValue = cs.callStmt.getInvokeExpr().getBase();
|
|
872
|
+
const containerValueProcess = (argIndex) => {
|
|
873
|
+
let srcNode = this.pag.getOrNewNode(cid, cs.args[argIndex], cs.callStmt);
|
|
874
|
+
let realContainerFieldPagNode = this.pag.getOrClonePagContainerFieldNode(baseClassPTNode, undefined, containerValue);
|
|
875
|
+
if (realContainerFieldPagNode) {
|
|
876
|
+
// In some cases, the value of a variable of array type may not be an explicit array object,
|
|
877
|
+
// and the value of `realContainerFieldPagNode` will be undefined.
|
|
878
|
+
this.pag.addPagEdge(srcNode, realContainerFieldPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
|
|
879
|
+
srcNodes.push(srcNode.getID());
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
if ((0, PTAUtils_1.IsCollectionSetAdd)(calleeMethod.getSignature())) {
|
|
883
|
+
containerValueProcess(0);
|
|
884
|
+
}
|
|
885
|
+
else if ((0, PTAUtils_1.IsCollectionMapSet)(calleeMethod.getSignature())) {
|
|
886
|
+
containerValueProcess(1);
|
|
887
|
+
}
|
|
888
|
+
return srcNodes;
|
|
889
|
+
}
|
|
890
|
+
getOrNewPagNode(cid, v, s) {
|
|
891
|
+
if (v instanceof Ref_1.ArkThisRef) {
|
|
892
|
+
return this.getOrNewThisRefNode(cid, v);
|
|
893
|
+
}
|
|
894
|
+
// this local is also not uniq!!!
|
|
895
|
+
// remove below block once this issue fixed
|
|
896
|
+
// globalThis process can not be removed while all `globalThis` ref is the same Value
|
|
897
|
+
if (v instanceof Local_1.Local) {
|
|
898
|
+
if (v.getName() === "this") {
|
|
899
|
+
return this.getOrNewThisLoalNode(cid, v, s);
|
|
900
|
+
}
|
|
901
|
+
else if (v.getName() === TSConst_1.GLOBAL_THIS_NAME && v.getDeclaringStmt() == null) {
|
|
902
|
+
// globalThis node has no cid
|
|
903
|
+
return this.getOrNewGlobalThisNode(-1);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
if (v instanceof Ref_1.ArkInstanceFieldRef || v instanceof Ref_1.ArkStaticFieldRef) {
|
|
907
|
+
v = this.getRealInstanceRef(v);
|
|
908
|
+
}
|
|
909
|
+
return this.pag.getOrNewNode(cid, v, s);
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* return ThisRef PAG node according to cid, a cid has a unique ThisRef node
|
|
913
|
+
* @param cid: current contextID
|
|
914
|
+
*/
|
|
915
|
+
getOrNewThisRefNode(cid, v) {
|
|
916
|
+
let thisRefNodeID = this.cid2ThisRefMap.get(cid);
|
|
917
|
+
if (!thisRefNodeID) {
|
|
918
|
+
thisRefNodeID = -1;
|
|
919
|
+
}
|
|
920
|
+
let thisRefNode = this.pag.getOrNewThisRefNode(thisRefNodeID, v);
|
|
921
|
+
this.cid2ThisRefMap.set(cid, thisRefNode.getID());
|
|
922
|
+
return thisRefNode;
|
|
923
|
+
}
|
|
924
|
+
// TODO: remove it once this local not uniq issue is fixed
|
|
925
|
+
getOrNewThisLoalNode(cid, v, s) {
|
|
926
|
+
let thisLocalNodeID = this.cid2ThisLocalMap.get(cid);
|
|
927
|
+
if (thisLocalNodeID) {
|
|
928
|
+
return this.pag.getNode(thisLocalNodeID);
|
|
929
|
+
}
|
|
930
|
+
let thisNode = this.pag.getOrNewNode(cid, v, s);
|
|
931
|
+
this.cid2ThisLocalMap.set(cid, thisNode.getID());
|
|
932
|
+
return thisNode;
|
|
933
|
+
}
|
|
934
|
+
getOrNewGlobalThisNode(cid) {
|
|
935
|
+
return this.pag.getOrNewNode(cid, this.getGlobalThisValue());
|
|
936
|
+
}
|
|
937
|
+
getUniqThisLocalNode(cid) {
|
|
938
|
+
return this.cid2ThisLocalMap.get(cid);
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* search the storage map to get propertyNode with given storage and propertyFieldName
|
|
942
|
+
* @param storage storage type: AppStorage, LocalStorage etc.
|
|
943
|
+
* @param propertyName string property key
|
|
944
|
+
* @returns propertyNode: PagLocalNode
|
|
945
|
+
*/
|
|
946
|
+
getOrNewPropertyNode(storage, propertyName, stmt) {
|
|
947
|
+
let propertyNode = this.getPropertyNode(storage, propertyName, stmt);
|
|
948
|
+
if (propertyNode) {
|
|
949
|
+
return propertyNode;
|
|
950
|
+
}
|
|
951
|
+
let storageMap = this.storagePropertyMap.get(storage);
|
|
952
|
+
let propertyLocal = new Local_1.Local(propertyName);
|
|
953
|
+
storageMap.set(propertyName, propertyLocal);
|
|
954
|
+
this.storagePropertyMap.set(storage, storageMap);
|
|
955
|
+
return this.getOrNewPagNode(-1, propertyLocal, stmt);
|
|
956
|
+
}
|
|
957
|
+
getPropertyNode(storage, propertyName, stmt) {
|
|
958
|
+
let storageMap = this.storagePropertyMap.get(storage);
|
|
959
|
+
let propertyLocal;
|
|
960
|
+
if (!storageMap) {
|
|
961
|
+
storageMap = new Map();
|
|
962
|
+
this.storagePropertyMap.set(storage, storageMap);
|
|
963
|
+
}
|
|
964
|
+
if (storageMap.has(propertyName)) {
|
|
965
|
+
propertyLocal = storageMap.get(propertyName);
|
|
966
|
+
}
|
|
967
|
+
if (propertyLocal) {
|
|
968
|
+
return this.getOrNewPagNode(-1, propertyLocal, stmt);
|
|
969
|
+
}
|
|
970
|
+
return undefined;
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* add PagEdge
|
|
974
|
+
* @param edgeKind: edge kind differs from API
|
|
975
|
+
* @param propertyNode: PAG node created by protpertyName
|
|
976
|
+
* @param obj: heapObj stored with Storage API
|
|
977
|
+
*/
|
|
978
|
+
addPropertyLinkEdge(propertyNode, storageObj, cid, stmt, edgeKind) {
|
|
979
|
+
if (!(storageObj.getType() instanceof Type_1.ClassType)) {
|
|
980
|
+
return false;
|
|
981
|
+
}
|
|
982
|
+
if (edgeKind === Pag_1.StorageLinkEdgeType.Property2Local) {
|
|
983
|
+
// propertyNode --> objNode
|
|
984
|
+
this.pag.addPagEdge(propertyNode, this.pag.getOrNewNode(cid, storageObj), Pag_1.PagEdgeKind.Copy, stmt);
|
|
985
|
+
}
|
|
986
|
+
else if (edgeKind === Pag_1.StorageLinkEdgeType.Local2Property) {
|
|
987
|
+
// propertyNode <-- objNode
|
|
988
|
+
this.pag.addPagEdge(this.pag.getOrNewNode(cid, storageObj), propertyNode, Pag_1.PagEdgeKind.Copy, stmt);
|
|
989
|
+
}
|
|
990
|
+
else if (edgeKind === Pag_1.StorageLinkEdgeType.TwoWay) {
|
|
991
|
+
// propertyNode <-> objNode
|
|
992
|
+
this.pag.addPagEdge(propertyNode, this.pag.getOrNewNode(cid, storageObj), Pag_1.PagEdgeKind.Copy, stmt);
|
|
993
|
+
this.pag.addPagEdge(this.pag.getOrNewNode(cid, storageObj), propertyNode, Pag_1.PagEdgeKind.Copy, stmt);
|
|
994
|
+
}
|
|
995
|
+
return true;
|
|
996
|
+
}
|
|
997
|
+
/*
|
|
998
|
+
* In ArkIR, ArkField has multiple instances for each stmt which use it
|
|
999
|
+
* But the unique one is needed for pointer analysis
|
|
1000
|
+
* This is a temp solution to use a ArkField->(first instance)
|
|
1001
|
+
* as the unique instance
|
|
1002
|
+
*
|
|
1003
|
+
* node merge condition:
|
|
1004
|
+
* instance field: value and ArkField
|
|
1005
|
+
* static field: ArkField
|
|
1006
|
+
*/
|
|
1007
|
+
getRealInstanceRef(v) {
|
|
1008
|
+
if (!(v instanceof Ref_1.ArkInstanceFieldRef || v instanceof Ref_1.ArkStaticFieldRef)) {
|
|
1009
|
+
return v;
|
|
1010
|
+
}
|
|
1011
|
+
let sig = v.getFieldSignature();
|
|
1012
|
+
let sigStr = sig.toString();
|
|
1013
|
+
let base;
|
|
1014
|
+
let real;
|
|
1015
|
+
if (v instanceof Ref_1.ArkInstanceFieldRef) {
|
|
1016
|
+
base = v.getBase();
|
|
1017
|
+
if (base instanceof Local_1.Local && base.getName() === TSConst_1.GLOBAL_THIS_NAME && base.getDeclaringStmt() == null) {
|
|
1018
|
+
// replace the base in fieldRef
|
|
1019
|
+
base = this.getGlobalThisValue();
|
|
1020
|
+
v.setBase(base);
|
|
1021
|
+
}
|
|
1022
|
+
let key = `${base.getSignature()}-${sigStr}`;
|
|
1023
|
+
real = this.instanceField2UniqInstanceMap.get(key);
|
|
1024
|
+
if (!real) {
|
|
1025
|
+
this.instanceField2UniqInstanceMap.set(key, v);
|
|
1026
|
+
real = v;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
else {
|
|
1030
|
+
real = this.staticField2UniqInstanceMap.get(sigStr);
|
|
1031
|
+
if (!real) {
|
|
1032
|
+
this.staticField2UniqInstanceMap.set(sigStr, v);
|
|
1033
|
+
real = v;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
return real;
|
|
1037
|
+
}
|
|
1038
|
+
/**
|
|
1039
|
+
* check if a method is singleton function
|
|
1040
|
+
* rule: static method, assign heap obj to global var or static field, return the receiver
|
|
1041
|
+
*/
|
|
1042
|
+
isSingletonFunction(funcID) {
|
|
1043
|
+
if (this.singletonFuncMap.has(funcID)) {
|
|
1044
|
+
return this.singletonFuncMap.get(funcID);
|
|
1045
|
+
}
|
|
1046
|
+
let arkMethod = this.cg.getArkMethodByFuncID(funcID);
|
|
1047
|
+
if (!arkMethod) {
|
|
1048
|
+
this.singletonFuncMap.set(funcID, false);
|
|
1049
|
+
return false;
|
|
1050
|
+
}
|
|
1051
|
+
if (!arkMethod.isStatic()) {
|
|
1052
|
+
this.singletonFuncMap.set(funcID, false);
|
|
1053
|
+
return false;
|
|
1054
|
+
}
|
|
1055
|
+
let funcPag = this.funcPags.get(funcID);
|
|
1056
|
+
let heapObjects = [...funcPag.getInternalEdges()]
|
|
1057
|
+
.filter(edge => edge.kind === Pag_1.PagEdgeKind.Address)
|
|
1058
|
+
.map(edge => edge.dst);
|
|
1059
|
+
let returnValues = arkMethod.getReturnValues();
|
|
1060
|
+
let result = this.isValueConnected([...funcPag.getInternalEdges()], heapObjects, returnValues);
|
|
1061
|
+
this.singletonFuncMap.set(funcID, result);
|
|
1062
|
+
if (result) {
|
|
1063
|
+
logger.info(`function ${funcID} is marked as singleton function`);
|
|
1064
|
+
}
|
|
1065
|
+
return result;
|
|
1066
|
+
}
|
|
1067
|
+
isValueConnected(edges, leftNodes, targetNodes) {
|
|
1068
|
+
// build funcPag graph
|
|
1069
|
+
const graph = new Map();
|
|
1070
|
+
let hasStaticFieldOrGlobalVar = false;
|
|
1071
|
+
for (const edge of edges) {
|
|
1072
|
+
let dst = this.getRealInstanceRef(edge.dst);
|
|
1073
|
+
let src = this.getRealInstanceRef(edge.src);
|
|
1074
|
+
if (!graph.has(dst)) {
|
|
1075
|
+
graph.set(dst, []);
|
|
1076
|
+
}
|
|
1077
|
+
if (!graph.has(src)) {
|
|
1078
|
+
graph.set(src, []);
|
|
1079
|
+
}
|
|
1080
|
+
if (dst instanceof Ref_1.ArkStaticFieldRef || src instanceof Ref_1.ArkStaticFieldRef) {
|
|
1081
|
+
hasStaticFieldOrGlobalVar = true;
|
|
1082
|
+
}
|
|
1083
|
+
graph.get(src).push(dst);
|
|
1084
|
+
}
|
|
1085
|
+
if (!hasStaticFieldOrGlobalVar) {
|
|
1086
|
+
return false;
|
|
1087
|
+
}
|
|
1088
|
+
for (const targetNode of targetNodes) {
|
|
1089
|
+
for (const leftNode of leftNodes) {
|
|
1090
|
+
const visited = new Set();
|
|
1091
|
+
let meetStaticField = false;
|
|
1092
|
+
if (this.funcPagDfs(graph, visited, leftNode, targetNode, meetStaticField)) {
|
|
1093
|
+
return true; // a value pair that satisfy condition
|
|
1094
|
+
}
|
|
1095
|
+
if (!meetStaticField) {
|
|
1096
|
+
break; // heap obj will not deal any more
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
return false;
|
|
1101
|
+
}
|
|
1102
|
+
funcPagDfs(graph, visited, currentNode, targetNode, staticFieldFound) {
|
|
1103
|
+
if (currentNode === targetNode) {
|
|
1104
|
+
return staticFieldFound;
|
|
1105
|
+
}
|
|
1106
|
+
visited.add(currentNode);
|
|
1107
|
+
for (const neighbor of graph.get(currentNode) || []) {
|
|
1108
|
+
// TODO: add global variable
|
|
1109
|
+
const isSpecialNode = neighbor instanceof Ref_1.ArkStaticFieldRef;
|
|
1110
|
+
if (!visited.has(neighbor)) {
|
|
1111
|
+
if (isSpecialNode) {
|
|
1112
|
+
staticFieldFound = true;
|
|
1113
|
+
}
|
|
1114
|
+
if (this.funcPagDfs(graph, visited, neighbor, targetNode, staticFieldFound)) {
|
|
1115
|
+
return true;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
return false;
|
|
1120
|
+
}
|
|
1121
|
+
getGlobalThisValue() {
|
|
1122
|
+
return this.globalThisValue;
|
|
1123
|
+
}
|
|
1124
|
+
getEdgeKindForAssignStmt(stmt) {
|
|
1125
|
+
if (this.stmtIsCreateAddressObj(stmt)) {
|
|
1126
|
+
return Pag_1.PagEdgeKind.Address;
|
|
1127
|
+
}
|
|
1128
|
+
if (this.stmtIsCopyKind(stmt)) {
|
|
1129
|
+
return Pag_1.PagEdgeKind.Copy;
|
|
1130
|
+
}
|
|
1131
|
+
if (this.stmtIsReadKind(stmt)) {
|
|
1132
|
+
return Pag_1.PagEdgeKind.Load;
|
|
1133
|
+
}
|
|
1134
|
+
if (this.stmtIsWriteKind(stmt)) {
|
|
1135
|
+
return Pag_1.PagEdgeKind.Write;
|
|
1136
|
+
}
|
|
1137
|
+
return Pag_1.PagEdgeKind.Unknown;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* get storageType enum with method's Declaring ClassName
|
|
1141
|
+
*
|
|
1142
|
+
* @param storageName ClassName that method belongs to, currently support AppStorage and SubscribedAbstractProperty
|
|
1143
|
+
* SubscribedAbstractProperty: in following listing, `link1` is infered as ClassType `SubscribedAbstractProperty`,
|
|
1144
|
+
* it needs to get PAG node to check the StorageType
|
|
1145
|
+
* let link1: SubscribedAbstractProperty<A> = AppStorage.link('PropA');
|
|
1146
|
+
* link1.set(a);
|
|
1147
|
+
* @param cs: for search PAG node in SubscribedAbstractProperty
|
|
1148
|
+
* @param cid: for search PAG node in SubscribedAbstractProperty
|
|
1149
|
+
* @returns StorageType enum
|
|
1150
|
+
*/
|
|
1151
|
+
getStorageType(storageName, cs, cid) {
|
|
1152
|
+
switch (storageName) {
|
|
1153
|
+
case 'AppStorage':
|
|
1154
|
+
return Pag_1.StorageType.APP_STORAGE;
|
|
1155
|
+
case 'SubscribedAbstractProperty': {
|
|
1156
|
+
let calleeBaseLocal = cs.callStmt.getInvokeExpr().getBase();
|
|
1157
|
+
let calleeBaseLocalNode = this.pag.getOrNewNode(cid, calleeBaseLocal);
|
|
1158
|
+
if (calleeBaseLocalNode.isStorageLinked()) {
|
|
1159
|
+
let storage = calleeBaseLocalNode.getStorage();
|
|
1160
|
+
return storage.StorageType;
|
|
1161
|
+
}
|
|
1162
|
+
return Pag_1.StorageType.Undefined;
|
|
1163
|
+
}
|
|
1164
|
+
default:
|
|
1165
|
+
return Pag_1.StorageType.Undefined;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
/**\
|
|
1169
|
+
* ArkNewExpr, ArkNewArrayExpr, function ptr, globalThis
|
|
1170
|
+
*/
|
|
1171
|
+
stmtIsCreateAddressObj(stmt) {
|
|
1172
|
+
let lhOp = stmt.getLeftOp();
|
|
1173
|
+
let rhOp = stmt.getRightOp();
|
|
1174
|
+
if ((rhOp instanceof Expr_1.ArkNewExpr || rhOp instanceof Expr_1.ArkNewArrayExpr) ||
|
|
1175
|
+
(lhOp instanceof Local_1.Local && ((rhOp instanceof Local_1.Local && rhOp.getType() instanceof Type_1.FunctionType &&
|
|
1176
|
+
rhOp.getDeclaringStmt() === null) ||
|
|
1177
|
+
(rhOp instanceof Ref_1.AbstractFieldRef && rhOp.getType() instanceof Type_1.FunctionType))) ||
|
|
1178
|
+
(rhOp instanceof Local_1.Local && rhOp.getName() === TSConst_1.GLOBAL_THIS_NAME && rhOp.getDeclaringStmt() == null)) {
|
|
1179
|
+
return true;
|
|
1180
|
+
}
|
|
1181
|
+
// TODO: add other Address Obj creation
|
|
1182
|
+
// like static object
|
|
1183
|
+
return false;
|
|
1184
|
+
}
|
|
1185
|
+
stmtIsCopyKind(stmt) {
|
|
1186
|
+
let lhOp = stmt.getLeftOp();
|
|
1187
|
+
let rhOp = stmt.getRightOp();
|
|
1188
|
+
let condition = (lhOp instanceof Local_1.Local && (rhOp instanceof Local_1.Local || rhOp instanceof Ref_1.ArkParameterRef ||
|
|
1189
|
+
rhOp instanceof Ref_1.ArkThisRef || rhOp instanceof Ref_1.ArkStaticFieldRef)) ||
|
|
1190
|
+
(lhOp instanceof Ref_1.ArkStaticFieldRef && rhOp instanceof Local_1.Local);
|
|
1191
|
+
if (condition) {
|
|
1192
|
+
return true;
|
|
1193
|
+
}
|
|
1194
|
+
return false;
|
|
1195
|
+
}
|
|
1196
|
+
stmtIsWriteKind(stmt) {
|
|
1197
|
+
let lhOp = stmt.getLeftOp();
|
|
1198
|
+
let rhOp = stmt.getRightOp();
|
|
1199
|
+
if (rhOp instanceof Local_1.Local &&
|
|
1200
|
+
(lhOp instanceof Ref_1.ArkInstanceFieldRef || lhOp instanceof Ref_1.ArkArrayRef)) {
|
|
1201
|
+
return true;
|
|
1202
|
+
}
|
|
1203
|
+
return false;
|
|
1204
|
+
}
|
|
1205
|
+
stmtIsReadKind(stmt) {
|
|
1206
|
+
let lhOp = stmt.getLeftOp();
|
|
1207
|
+
let rhOp = stmt.getRightOp();
|
|
1208
|
+
if (lhOp instanceof Local_1.Local &&
|
|
1209
|
+
(rhOp instanceof Ref_1.ArkInstanceFieldRef || rhOp instanceof Ref_1.ArkArrayRef)) {
|
|
1210
|
+
return true;
|
|
1211
|
+
}
|
|
1212
|
+
return false;
|
|
1213
|
+
}
|
|
1214
|
+
addToDynamicCallSite(funcPag, cs) {
|
|
1215
|
+
var _a;
|
|
1216
|
+
funcPag.addDynamicCallSite(cs);
|
|
1217
|
+
this.pagStat.numDynamicCall++;
|
|
1218
|
+
logger.trace("[add dynamic callsite] " + cs.callStmt.toString() + ": " + ((_a = cs.callStmt.getCfg()) === null || _a === void 0 ? void 0 : _a.getDeclaringMethod().getSignature().toString()));
|
|
1219
|
+
}
|
|
1220
|
+
setPtForNode(node, pts) {
|
|
1221
|
+
if (!pts) {
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
this.pag.getNode(node).setPointTo(pts);
|
|
1225
|
+
}
|
|
1226
|
+
getRealThisLocal(input, funcId) {
|
|
1227
|
+
var _a;
|
|
1228
|
+
if (input.getName() !== 'this')
|
|
1229
|
+
return input;
|
|
1230
|
+
let real = input;
|
|
1231
|
+
let f = this.cg.getArkMethodByFuncID(funcId);
|
|
1232
|
+
(_a = f === null || f === void 0 ? void 0 : f.getCfg()) === null || _a === void 0 ? void 0 : _a.getStmts().forEach(s => {
|
|
1233
|
+
if (s instanceof Stmt_1.ArkAssignStmt && s.getLeftOp() instanceof Local_1.Local) {
|
|
1234
|
+
if (s.getLeftOp().getName() === 'this') {
|
|
1235
|
+
real = s.getLeftOp();
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
return real;
|
|
1241
|
+
}
|
|
1242
|
+
doStat() {
|
|
1243
|
+
this.pagStat.numTotalNode = this.pag.getNodeNum();
|
|
1244
|
+
}
|
|
1245
|
+
printStat() {
|
|
1246
|
+
this.pagStat.printStat();
|
|
1247
|
+
}
|
|
1248
|
+
getStat() {
|
|
1249
|
+
return this.pagStat.getStat();
|
|
1250
|
+
}
|
|
1251
|
+
getUnhandledFuncs() {
|
|
1252
|
+
let handledFuncs = this.getHandledFuncs();
|
|
1253
|
+
let unhandleFuncs = Array.from(this.cg.getNodesIter())
|
|
1254
|
+
.filter(f => !handledFuncs.includes(f.getID()))
|
|
1255
|
+
.map(f => f.getID());
|
|
1256
|
+
return unhandleFuncs;
|
|
1257
|
+
}
|
|
1258
|
+
getHandledFuncs() {
|
|
1259
|
+
return Array.from(this.funcPags.keys());
|
|
1260
|
+
}
|
|
1261
|
+
/**
|
|
1262
|
+
* build export edge in internal func pag
|
|
1263
|
+
* @param value: Value that need to check if it is from import/export
|
|
1264
|
+
* @param originValue: if Value if InstanceFieldRef, the base will be passed to `value` recursively,
|
|
1265
|
+
* fieldRef will be passed to `originValue`
|
|
1266
|
+
*/
|
|
1267
|
+
handleValueFromExternalScope(value, funcID, originValue) {
|
|
1268
|
+
if (value instanceof Local_1.Local) {
|
|
1269
|
+
if (value.getDeclaringStmt()) {
|
|
1270
|
+
// not from external scope
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1273
|
+
if (!value.getType()) {
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
let srcLocal = this.getSourceValueFromExternalScope(value, funcID);
|
|
1277
|
+
if (srcLocal) {
|
|
1278
|
+
// if `value` is from field base, use origin value(fieldRef) instead
|
|
1279
|
+
this.addInterFuncEdge(srcLocal, originValue !== null && originValue !== void 0 ? originValue : value, funcID);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
else if (value instanceof Ref_1.ArkInstanceFieldRef) {
|
|
1283
|
+
let base = value.getBase();
|
|
1284
|
+
if (base) {
|
|
1285
|
+
this.handleValueFromExternalScope(base, funcID, value);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
addInterFuncEdge(src, dst, funcID) {
|
|
1290
|
+
var _a, _b, _c;
|
|
1291
|
+
this.interFuncPags = (_a = this.interFuncPags) !== null && _a !== void 0 ? _a : new Map();
|
|
1292
|
+
let interFuncPag = (_b = this.interFuncPags.get(funcID)) !== null && _b !== void 0 ? _b : new Pag_1.InterFuncPag();
|
|
1293
|
+
// Export a local
|
|
1294
|
+
// Add a InterProcedural edge
|
|
1295
|
+
if (dst instanceof Local_1.Local) {
|
|
1296
|
+
let e = { src: src, dst: dst, kind: Pag_1.PagEdgeKind.InterProceduralCopy };
|
|
1297
|
+
interFuncPag.addToInterProceduralEdgeSet(e);
|
|
1298
|
+
this.addExportVariableMap(src, dst);
|
|
1299
|
+
}
|
|
1300
|
+
else if (dst instanceof Ref_1.ArkInstanceFieldRef) {
|
|
1301
|
+
// record the export base use
|
|
1302
|
+
this.addExportVariableMap(src, dst.getBase());
|
|
1303
|
+
}
|
|
1304
|
+
this.interFuncPags.set(funcID, interFuncPag);
|
|
1305
|
+
// Put the function which the src belongs to to worklist
|
|
1306
|
+
let srcFunc = (_c = src.getDeclaringStmt()) === null || _c === void 0 ? void 0 : _c.getCfg().getDeclaringMethod();
|
|
1307
|
+
if (srcFunc) {
|
|
1308
|
+
let srcFuncID = this.cg.getCallGraphNodeByMethod(srcFunc.getSignature()).getID();
|
|
1309
|
+
let cid = this.ctx.getNewContextID(srcFuncID);
|
|
1310
|
+
let csFuncID = new CSFuncID(cid, srcFuncID);
|
|
1311
|
+
this.buildFuncPagAndAddToWorklist(csFuncID);
|
|
1312
|
+
}
|
|
1313
|
+
// Extend other types of src here
|
|
1314
|
+
}
|
|
1315
|
+
getSourceValueFromExternalScope(value, funcID) {
|
|
1316
|
+
let sourceValue;
|
|
1317
|
+
// TODO: first from default method
|
|
1318
|
+
sourceValue = this.getDefaultMethodSourceValue(value, funcID);
|
|
1319
|
+
if (!sourceValue) {
|
|
1320
|
+
sourceValue = this.getExportSourceValue(value, funcID);
|
|
1321
|
+
}
|
|
1322
|
+
return sourceValue;
|
|
1323
|
+
}
|
|
1324
|
+
getDefaultMethodSourceValue(value, funcID) {
|
|
1325
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1326
|
+
// namespace check
|
|
1327
|
+
let arkMethod = this.cg.getArkMethodByFuncID(funcID);
|
|
1328
|
+
if (!arkMethod) {
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
let declaringNameSpace = arkMethod.getDeclaringArkClass().getDeclaringArkNamespace();
|
|
1332
|
+
while (declaringNameSpace) {
|
|
1333
|
+
let nameSpaceLocals = (_c = (_b = (_a = declaringNameSpace.getDefaultClass()
|
|
1334
|
+
.getDefaultArkMethod()) === null || _a === void 0 ? void 0 : _a.getBody()) === null || _b === void 0 ? void 0 : _b.getLocals()) !== null && _c !== void 0 ? _c : new Map();
|
|
1335
|
+
if (nameSpaceLocals.has(value.getName())) {
|
|
1336
|
+
return nameSpaceLocals.get(value.getName());
|
|
1337
|
+
}
|
|
1338
|
+
declaringNameSpace = (_d = declaringNameSpace.getDeclaringArkNamespace()) !== null && _d !== void 0 ? _d : undefined;
|
|
1339
|
+
}
|
|
1340
|
+
// file check
|
|
1341
|
+
let declaringFile = arkMethod.getDeclaringArkFile();
|
|
1342
|
+
let fileLocals = (_g = (_f = (_e = declaringFile.getDefaultClass()
|
|
1343
|
+
.getDefaultArkMethod()) === null || _e === void 0 ? void 0 : _e.getBody()) === null || _f === void 0 ? void 0 : _f.getLocals()) !== null && _g !== void 0 ? _g : new Map();
|
|
1344
|
+
if (!fileLocals.has(value.getName())) {
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
return fileLocals.get(value.getName());
|
|
1348
|
+
}
|
|
1349
|
+
getExportSourceValue(value, funcID) {
|
|
1350
|
+
let curMethod = this.cg.getArkMethodByFuncID(funcID);
|
|
1351
|
+
if (!curMethod) {
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
let curFile = curMethod.getDeclaringArkFile();
|
|
1355
|
+
let impInfo = curFile.getImportInfoBy(value.getName());
|
|
1356
|
+
if (!impInfo) {
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
let exportSource = impInfo.getLazyExportInfo();
|
|
1360
|
+
if (!exportSource) {
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
let exportSouceValue = exportSource.getArkExport();
|
|
1364
|
+
if (exportSouceValue instanceof Local_1.Local) {
|
|
1365
|
+
return exportSouceValue;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
addExportVariableMap(src, dst) {
|
|
1369
|
+
var _a;
|
|
1370
|
+
let exportMap = (_a = this.externalScopeVariableMap.get(src)) !== null && _a !== void 0 ? _a : [];
|
|
1371
|
+
if (!exportMap.includes(dst)) {
|
|
1372
|
+
exportMap.push(dst);
|
|
1373
|
+
this.externalScopeVariableMap.set(src, exportMap);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
getExportVariableMap(src) {
|
|
1377
|
+
var _a;
|
|
1378
|
+
return (_a = this.externalScopeVariableMap.get(src)) !== null && _a !== void 0 ? _a : [];
|
|
1379
|
+
}
|
|
1380
|
+
/// Add inter-procedural Pag Nodes and Edges
|
|
1381
|
+
addEdgesFromInterFuncPag(interFuncPag, cid) {
|
|
1382
|
+
let edges = interFuncPag.getInterProceduralEdges();
|
|
1383
|
+
if (edges.size === 0) {
|
|
1384
|
+
return false;
|
|
1385
|
+
}
|
|
1386
|
+
for (let e of edges) {
|
|
1387
|
+
// Existing local exported nodes -> ExportNode
|
|
1388
|
+
let exportLocal = e.src;
|
|
1389
|
+
let dstPagNode = this.getOrNewPagNode(cid, e.dst);
|
|
1390
|
+
// get export local node in all cid
|
|
1391
|
+
let existingNodes = this.pag.getNodesByValue(exportLocal);
|
|
1392
|
+
existingNodes === null || existingNodes === void 0 ? void 0 : existingNodes.forEach(n => {
|
|
1393
|
+
this.pag.addPagEdge(this.pag.getNode(n), dstPagNode, e.kind);
|
|
1394
|
+
});
|
|
1395
|
+
}
|
|
1396
|
+
return true;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
exports.PagBuilder = PagBuilder;
|