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.
Files changed (279) hide show
  1. package/lib/Config.d.ts +70 -70
  2. package/lib/Config.js +198 -198
  3. package/lib/Scene.d.ts +316 -316
  4. package/lib/Scene.js +1316 -1316
  5. package/lib/callgraph/algorithm/AbstractAnalysis.d.ts +28 -28
  6. package/lib/callgraph/algorithm/AbstractAnalysis.js +144 -144
  7. package/lib/callgraph/algorithm/ClassHierarchyAnalysis.d.ts +10 -10
  8. package/lib/callgraph/algorithm/ClassHierarchyAnalysis.js +69 -69
  9. package/lib/callgraph/algorithm/RapidTypeAnalysis.d.ts +15 -15
  10. package/lib/callgraph/algorithm/RapidTypeAnalysis.js +146 -146
  11. package/lib/callgraph/common/Statistics.d.ts +57 -57
  12. package/lib/callgraph/common/Statistics.js +228 -228
  13. package/lib/callgraph/model/CallGraph.d.ts +96 -96
  14. package/lib/callgraph/model/CallGraph.js +354 -354
  15. package/lib/callgraph/model/builder/CallGraphBuilder.d.ts +15 -15
  16. package/lib/callgraph/model/builder/CallGraphBuilder.js +106 -106
  17. package/lib/callgraph/pointerAnalysis/Context.d.ts +37 -37
  18. package/lib/callgraph/pointerAnalysis/Context.js +155 -155
  19. package/lib/callgraph/pointerAnalysis/DummyCallCreator.d.ts +22 -22
  20. package/lib/callgraph/pointerAnalysis/DummyCallCreator.js +104 -104
  21. package/lib/callgraph/pointerAnalysis/PTAUtils.d.ts +5 -5
  22. package/lib/callgraph/pointerAnalysis/PTAUtils.js +46 -46
  23. package/lib/callgraph/pointerAnalysis/Pag.d.ts +261 -261
  24. package/lib/callgraph/pointerAnalysis/Pag.js +930 -930
  25. package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts +157 -157
  26. package/lib/callgraph/pointerAnalysis/PagBuilder.js +1399 -1399
  27. package/lib/callgraph/pointerAnalysis/PointerAnalysis.d.ts +72 -72
  28. package/lib/callgraph/pointerAnalysis/PointerAnalysis.js +573 -573
  29. package/lib/callgraph/pointerAnalysis/PointerAnalysisConfig.d.ts +15 -15
  30. package/lib/callgraph/pointerAnalysis/PointerAnalysisConfig.js +81 -81
  31. package/lib/callgraph/pointerAnalysis/PtsDS.d.ts +80 -80
  32. package/lib/callgraph/pointerAnalysis/PtsDS.js +308 -308
  33. package/lib/core/base/Constant.d.ts +48 -48
  34. package/lib/core/base/Constant.js +103 -103
  35. package/lib/core/base/Decorator.d.ts +15 -15
  36. package/lib/core/base/Decorator.js +46 -46
  37. package/lib/core/base/DefUseChain.d.ts +8 -8
  38. package/lib/core/base/DefUseChain.js +25 -25
  39. package/lib/core/base/Expr.d.ts +340 -340
  40. package/lib/core/base/Expr.js +917 -917
  41. package/lib/core/base/Local.d.ts +104 -104
  42. package/lib/core/base/Local.js +176 -176
  43. package/lib/core/base/Position.d.ts +30 -30
  44. package/lib/core/base/Position.js +147 -147
  45. package/lib/core/base/Ref.d.ts +173 -173
  46. package/lib/core/base/Ref.js +374 -374
  47. package/lib/core/base/Stmt.d.ts +237 -237
  48. package/lib/core/base/Stmt.js +525 -525
  49. package/lib/core/base/Trap.d.ts +8 -8
  50. package/lib/core/base/Trap.js +30 -30
  51. package/lib/core/base/Type.d.ts +308 -308
  52. package/lib/core/base/Type.js +639 -639
  53. package/lib/core/base/TypeExpr.d.ts +71 -71
  54. package/lib/core/base/TypeExpr.js +155 -155
  55. package/lib/core/base/Value.d.ts +32 -32
  56. package/lib/core/base/Value.js +16 -16
  57. package/lib/core/common/ArkError.d.ts +14 -14
  58. package/lib/core/common/ArkError.js +28 -28
  59. package/lib/core/common/ArkIRTransformer.d.ts +67 -67
  60. package/lib/core/common/ArkIRTransformer.js +690 -690
  61. package/lib/core/common/ArkValueTransformer.d.ts +89 -89
  62. package/lib/core/common/ArkValueTransformer.js +1478 -1478
  63. package/lib/core/common/Builtin.d.ts +36 -36
  64. package/lib/core/common/Builtin.js +81 -81
  65. package/lib/core/common/Const.d.ts +21 -21
  66. package/lib/core/common/Const.js +43 -43
  67. package/lib/core/common/DummyMainCreater.d.ts +46 -46
  68. package/lib/core/common/DummyMainCreater.js +319 -319
  69. package/lib/core/common/EtsConst.d.ts +73 -73
  70. package/lib/core/common/EtsConst.js +1021 -1021
  71. package/lib/core/common/ExprUseReplacer.d.ts +21 -21
  72. package/lib/core/common/ExprUseReplacer.js +124 -124
  73. package/lib/core/common/IRInference.d.ts +36 -36
  74. package/lib/core/common/IRInference.d.ts.map +1 -1
  75. package/lib/core/common/IRInference.js +651 -648
  76. package/lib/core/common/IRUtils.d.ts +18 -18
  77. package/lib/core/common/IRUtils.js +141 -141
  78. package/lib/core/common/ModelUtils.d.ts +70 -70
  79. package/lib/core/common/ModelUtils.js +712 -712
  80. package/lib/core/common/RefUseReplacer.d.ts +13 -13
  81. package/lib/core/common/RefUseReplacer.js +52 -52
  82. package/lib/core/common/SdkUtils.d.ts +8 -8
  83. package/lib/core/common/SdkUtils.js +105 -105
  84. package/lib/core/common/StmtDefReplacer.d.ts +12 -12
  85. package/lib/core/common/StmtDefReplacer.js +41 -41
  86. package/lib/core/common/StmtUseReplacer.d.ts +16 -16
  87. package/lib/core/common/StmtUseReplacer.js +108 -108
  88. package/lib/core/common/TSConst.d.ts +18 -18
  89. package/lib/core/common/TSConst.js +36 -36
  90. package/lib/core/common/TypeInference.d.ts +102 -102
  91. package/lib/core/common/TypeInference.js +748 -748
  92. package/lib/core/common/ValueUtil.d.ts +12 -12
  93. package/lib/core/common/ValueUtil.js +54 -54
  94. package/lib/core/common/VisibleValue.d.ts +36 -36
  95. package/lib/core/common/VisibleValue.js +212 -212
  96. package/lib/core/dataflow/DataflowProblem.d.ts +20 -20
  97. package/lib/core/dataflow/DataflowProblem.js +20 -20
  98. package/lib/core/dataflow/DataflowResult.d.ts +7 -7
  99. package/lib/core/dataflow/DataflowResult.js +26 -26
  100. package/lib/core/dataflow/DataflowSolver.d.ts +43 -43
  101. package/lib/core/dataflow/DataflowSolver.js +307 -307
  102. package/lib/core/dataflow/Edge.d.ts +11 -11
  103. package/lib/core/dataflow/Edge.js +31 -31
  104. package/lib/core/dataflow/Fact.d.ts +6 -6
  105. package/lib/core/dataflow/Fact.js +24 -24
  106. package/lib/core/dataflow/GenericDataFlow.d.ts +142 -142
  107. package/lib/core/dataflow/GenericDataFlow.js +109 -109
  108. package/lib/core/dataflow/ReachingDef.d.ts +62 -62
  109. package/lib/core/dataflow/ReachingDef.js +168 -168
  110. package/lib/core/dataflow/UndefinedVariable.d.ts +45 -45
  111. package/lib/core/dataflow/UndefinedVariable.js +288 -288
  112. package/lib/core/dataflow/Util.d.ts +9 -9
  113. package/lib/core/dataflow/Util.js +64 -64
  114. package/lib/core/graph/BaseExplicitGraph.d.ts +58 -58
  115. package/lib/core/graph/BaseExplicitGraph.js +157 -157
  116. package/lib/core/graph/BaseImplicitGraph.d.ts +77 -77
  117. package/lib/core/graph/BaseImplicitGraph.js +78 -78
  118. package/lib/core/graph/BasicBlock.d.ts +104 -104
  119. package/lib/core/graph/BasicBlock.js +280 -280
  120. package/lib/core/graph/Cfg.d.ts +59 -59
  121. package/lib/core/graph/Cfg.js +282 -282
  122. package/lib/core/graph/DependsGraph.d.ts +35 -35
  123. package/lib/core/graph/DependsGraph.js +87 -87
  124. package/lib/core/graph/DominanceFinder.d.ts +15 -15
  125. package/lib/core/graph/DominanceFinder.js +121 -121
  126. package/lib/core/graph/DominanceTree.d.ts +12 -12
  127. package/lib/core/graph/DominanceTree.js +70 -70
  128. package/lib/core/graph/GraphTraits.d.ts +7 -7
  129. package/lib/core/graph/GraphTraits.js +16 -16
  130. package/lib/core/graph/Scc.d.ts +61 -61
  131. package/lib/core/graph/Scc.js +222 -222
  132. package/lib/core/graph/ViewTree.d.ts +114 -114
  133. package/lib/core/graph/ViewTree.js +16 -16
  134. package/lib/core/graph/builder/CfgBuilder.d.ts +176 -176
  135. package/lib/core/graph/builder/CfgBuilder.js +1139 -1139
  136. package/lib/core/graph/builder/ConditionBuilder.d.ts +15 -15
  137. package/lib/core/graph/builder/ConditionBuilder.js +252 -252
  138. package/lib/core/graph/builder/LoopBuilder.d.ts +20 -20
  139. package/lib/core/graph/builder/LoopBuilder.js +251 -251
  140. package/lib/core/graph/builder/SwitchBuilder.d.ts +11 -11
  141. package/lib/core/graph/builder/SwitchBuilder.js +152 -152
  142. package/lib/core/graph/builder/TrapBuilder.d.ts +16 -16
  143. package/lib/core/graph/builder/TrapBuilder.js +272 -272
  144. package/lib/core/graph/builder/ViewTreeBuilder.d.ts +203 -203
  145. package/lib/core/graph/builder/ViewTreeBuilder.js +1055 -1055
  146. package/lib/core/model/ArkBaseModel.d.ts +59 -59
  147. package/lib/core/model/ArkBaseModel.js +274 -274
  148. package/lib/core/model/ArkBody.d.ts +24 -24
  149. package/lib/core/model/ArkBody.js +65 -65
  150. package/lib/core/model/ArkClass.d.ts +206 -206
  151. package/lib/core/model/ArkClass.js +439 -439
  152. package/lib/core/model/ArkExport.d.ts +72 -72
  153. package/lib/core/model/ArkExport.js +147 -147
  154. package/lib/core/model/ArkField.d.ts +62 -62
  155. package/lib/core/model/ArkField.js +113 -113
  156. package/lib/core/model/ArkFile.d.ts +131 -131
  157. package/lib/core/model/ArkFile.js +267 -267
  158. package/lib/core/model/ArkImport.d.ts +44 -44
  159. package/lib/core/model/ArkImport.js +108 -108
  160. package/lib/core/model/ArkMetadata.d.ts +31 -31
  161. package/lib/core/model/ArkMetadata.js +55 -55
  162. package/lib/core/model/ArkMethod.d.ts +261 -261
  163. package/lib/core/model/ArkMethod.js +592 -592
  164. package/lib/core/model/ArkNamespace.d.ts +66 -66
  165. package/lib/core/model/ArkNamespace.js +209 -209
  166. package/lib/core/model/ArkSignature.d.ts +162 -162
  167. package/lib/core/model/ArkSignature.js +379 -379
  168. package/lib/core/model/builder/ArkClassBuilder.d.ts +12 -12
  169. package/lib/core/model/builder/ArkClassBuilder.js +454 -454
  170. package/lib/core/model/builder/ArkExportBuilder.d.ts +24 -24
  171. package/lib/core/model/builder/ArkExportBuilder.js +210 -210
  172. package/lib/core/model/builder/ArkFieldBuilder.d.ts +8 -8
  173. package/lib/core/model/builder/ArkFieldBuilder.js +193 -193
  174. package/lib/core/model/builder/ArkFileBuilder.d.ts +9 -9
  175. package/lib/core/model/builder/ArkFileBuilder.js +165 -165
  176. package/lib/core/model/builder/ArkImportBuilder.d.ts +4 -4
  177. package/lib/core/model/builder/ArkImportBuilder.js +128 -128
  178. package/lib/core/model/builder/ArkMethodBuilder.d.ts +63 -63
  179. package/lib/core/model/builder/ArkMethodBuilder.js +486 -486
  180. package/lib/core/model/builder/ArkNamespaceBuilder.d.ts +5 -5
  181. package/lib/core/model/builder/ArkNamespaceBuilder.js +205 -205
  182. package/lib/core/model/builder/ArkSignatureBuilder.d.ts +8 -8
  183. package/lib/core/model/builder/ArkSignatureBuilder.js +40 -40
  184. package/lib/core/model/builder/BodyBuilder.d.ts +55 -30
  185. package/lib/core/model/builder/BodyBuilder.d.ts.map +1 -1
  186. package/lib/core/model/builder/BodyBuilder.js +542 -371
  187. package/lib/core/model/builder/builderUtils.d.ts +18 -18
  188. package/lib/core/model/builder/builderUtils.js +558 -558
  189. package/lib/index.d.ts +82 -80
  190. package/lib/index.d.ts.map +1 -1
  191. package/lib/index.js +201 -196
  192. package/lib/save/ArkStream.d.ts +23 -23
  193. package/lib/save/ArkStream.js +83 -83
  194. package/lib/save/DotPrinter.d.ts +43 -43
  195. package/lib/save/DotPrinter.js +170 -170
  196. package/lib/save/GraphPrinter.d.ts +16 -16
  197. package/lib/save/GraphPrinter.js +134 -134
  198. package/lib/save/JsonPrinter.d.ts +30 -30
  199. package/lib/save/JsonPrinter.js +580 -580
  200. package/lib/save/Printer.d.ts +12 -12
  201. package/lib/save/Printer.js +27 -27
  202. package/lib/save/PrinterBuilder.d.ts +53 -53
  203. package/lib/save/PrinterBuilder.js +145 -145
  204. package/lib/save/ViewTreePrinter.d.ts +14 -14
  205. package/lib/save/ViewTreePrinter.js +123 -123
  206. package/lib/save/arkir/ArkIRClassPrinter.d.ts +13 -13
  207. package/lib/save/arkir/ArkIRClassPrinter.js +92 -92
  208. package/lib/save/arkir/ArkIRFieldPrinter.d.ts +11 -11
  209. package/lib/save/arkir/ArkIRFieldPrinter.js +64 -64
  210. package/lib/save/arkir/ArkIRFilePrinter.d.ts +12 -12
  211. package/lib/save/arkir/ArkIRFilePrinter.js +54 -54
  212. package/lib/save/arkir/ArkIRMethodPrinter.d.ts +16 -16
  213. package/lib/save/arkir/ArkIRMethodPrinter.js +159 -159
  214. package/lib/save/arkir/ArkIRNamespacePrinter.d.ts +11 -11
  215. package/lib/save/arkir/ArkIRNamespacePrinter.js +66 -66
  216. package/lib/save/base/BasePrinter.d.ts +23 -23
  217. package/lib/save/base/BasePrinter.js +70 -70
  218. package/lib/save/base/ExportPrinter.d.ts +8 -8
  219. package/lib/save/base/ExportPrinter.js +67 -67
  220. package/lib/save/base/ImportPrinter.d.ts +9 -9
  221. package/lib/save/base/ImportPrinter.js +92 -92
  222. package/lib/save/base/PrinterUtils.d.ts +24 -24
  223. package/lib/save/base/PrinterUtils.js +208 -208
  224. package/lib/save/serializeArkIR.d.ts +8 -8
  225. package/lib/save/serializeArkIR.js +294 -294
  226. package/lib/save/source/SourceBase.d.ts +22 -22
  227. package/lib/save/source/SourceBase.js +64 -64
  228. package/lib/save/source/SourceBody.d.ts +58 -58
  229. package/lib/save/source/SourceBody.js +296 -296
  230. package/lib/save/source/SourceClass.d.ts +25 -25
  231. package/lib/save/source/SourceClass.js +187 -187
  232. package/lib/save/source/SourceField.d.ts +13 -13
  233. package/lib/save/source/SourceField.js +73 -73
  234. package/lib/save/source/SourceFilePrinter.d.ts +12 -12
  235. package/lib/save/source/SourceFilePrinter.js +69 -69
  236. package/lib/save/source/SourceMethod.d.ts +22 -22
  237. package/lib/save/source/SourceMethod.d.ts.map +1 -1
  238. package/lib/save/source/SourceMethod.js +196 -193
  239. package/lib/save/source/SourceNamespace.d.ts +11 -11
  240. package/lib/save/source/SourceNamespace.js +83 -83
  241. package/lib/save/source/SourceStmt.d.ts +178 -178
  242. package/lib/save/source/SourceStmt.js +838 -838
  243. package/lib/save/source/SourceTransformer.d.ts +46 -46
  244. package/lib/save/source/SourceTransformer.js +446 -446
  245. package/lib/transformer/FunctionTransformer.d.ts +2 -2
  246. package/lib/transformer/FunctionTransformer.js +17 -17
  247. package/lib/transformer/SceneTransformer.d.ts +2 -2
  248. package/lib/transformer/SceneTransformer.js +17 -17
  249. package/lib/transformer/StaticSingleAssignmentFormer.d.ts +12 -12
  250. package/lib/transformer/StaticSingleAssignmentFormer.js +259 -259
  251. package/lib/transformer/Transformer.d.ts +6 -6
  252. package/lib/transformer/Transformer.js +22 -22
  253. package/lib/utils/AstTreeUtils.d.ts +4 -4
  254. package/lib/utils/AstTreeUtils.js +26 -26
  255. package/lib/utils/CfgStructualAnalysis.d.ts +110 -110
  256. package/lib/utils/CfgStructualAnalysis.js +1277 -1277
  257. package/lib/utils/FileUtils.d.ts +18 -18
  258. package/lib/utils/FileUtils.js +135 -135
  259. package/lib/utils/SparseBitVector.d.ts +100 -100
  260. package/lib/utils/SparseBitVector.js +445 -445
  261. package/lib/utils/callGraphUtils.d.ts +30 -30
  262. package/lib/utils/callGraphUtils.js +205 -205
  263. package/lib/utils/crypto_utils.d.ts +5 -5
  264. package/lib/utils/crypto_utils.js +57 -57
  265. package/lib/utils/entryMethodUtils.d.ts +13 -13
  266. package/lib/utils/entryMethodUtils.js +110 -110
  267. package/lib/utils/getAllFiles.d.ts +9 -9
  268. package/lib/utils/getAllFiles.js +90 -90
  269. package/lib/utils/json5parser.d.ts +6 -6
  270. package/lib/utils/json5parser.js +146 -146
  271. package/lib/utils/logger.d.ts +18 -18
  272. package/lib/utils/logger.d.ts.map +1 -1
  273. package/lib/utils/logger.js +97 -90
  274. package/lib/utils/pathTransfer.d.ts +1 -1
  275. package/lib/utils/pathTransfer.js +25 -25
  276. package/node_modules/json5/lib/cli.js +0 -0
  277. package/node_modules/ohos-typescript/bin/tsc +0 -0
  278. package/node_modules/ohos-typescript/bin/tsserver +0 -0
  279. 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;