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