arkanalyzer 1.0.7 → 1.0.9

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 (164) hide show
  1. package/config/arkanalyzer.json +8 -0
  2. package/lib/Config.d.ts +9 -1
  3. package/lib/Config.d.ts.map +1 -1
  4. package/lib/Config.js +24 -11
  5. package/lib/Scene.d.ts +49 -42
  6. package/lib/Scene.d.ts.map +1 -1
  7. package/lib/Scene.js +124 -93
  8. package/lib/callgraph/algorithm/AbstractAnalysis.js +1 -1
  9. package/lib/callgraph/common/Statistics.js +1 -1
  10. package/lib/callgraph/model/CallGraph.d.ts +3 -2
  11. package/lib/callgraph/model/CallGraph.d.ts.map +1 -1
  12. package/lib/callgraph/model/CallGraph.js +15 -5
  13. package/lib/callgraph/model/builder/CallGraphBuilder.js +1 -1
  14. package/lib/callgraph/pointerAnalysis/Pag.d.ts +35 -8
  15. package/lib/callgraph/pointerAnalysis/Pag.d.ts.map +1 -1
  16. package/lib/callgraph/pointerAnalysis/Pag.js +89 -8
  17. package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts +32 -5
  18. package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts.map +1 -1
  19. package/lib/callgraph/pointerAnalysis/PagBuilder.js +378 -83
  20. package/lib/callgraph/pointerAnalysis/PointerAnalysis.d.ts +3 -0
  21. package/lib/callgraph/pointerAnalysis/PointerAnalysis.d.ts.map +1 -1
  22. package/lib/callgraph/pointerAnalysis/PointerAnalysis.js +71 -18
  23. package/lib/core/base/Constant.d.ts +25 -5
  24. package/lib/core/base/Constant.d.ts.map +1 -1
  25. package/lib/core/base/Constant.js +46 -8
  26. package/lib/core/base/Expr.d.ts +45 -40
  27. package/lib/core/base/Expr.d.ts.map +1 -1
  28. package/lib/core/base/Expr.js +236 -150
  29. package/lib/core/base/Local.d.ts +2 -2
  30. package/lib/core/base/Local.d.ts.map +1 -1
  31. package/lib/core/base/Local.js +2 -2
  32. package/lib/core/base/Ref.d.ts +38 -37
  33. package/lib/core/base/Ref.d.ts.map +1 -1
  34. package/lib/core/base/Ref.js +102 -70
  35. package/lib/core/base/Stmt.d.ts +4 -0
  36. package/lib/core/base/Stmt.d.ts.map +1 -1
  37. package/lib/core/base/Stmt.js +12 -1
  38. package/lib/core/base/Type.d.ts +4 -0
  39. package/lib/core/base/Type.d.ts.map +1 -1
  40. package/lib/core/base/Type.js +41 -17
  41. package/lib/core/common/ArkError.d.ts +15 -0
  42. package/lib/core/common/ArkError.d.ts.map +1 -0
  43. package/lib/core/common/ArkError.js +28 -0
  44. package/lib/core/common/ArkIRTransformer.d.ts +1 -1
  45. package/lib/core/common/ArkIRTransformer.d.ts.map +1 -1
  46. package/lib/core/common/ArkIRTransformer.js +24 -8
  47. package/lib/core/common/CfgBuilder.d.ts.map +1 -1
  48. package/lib/core/common/CfgBuilder.js +5 -0
  49. package/lib/core/common/Const.d.ts +15 -10
  50. package/lib/core/common/Const.d.ts.map +1 -1
  51. package/lib/core/common/Const.js +18 -11
  52. package/lib/core/common/DummyMainCreater.d.ts +2 -1
  53. package/lib/core/common/DummyMainCreater.d.ts.map +1 -1
  54. package/lib/core/common/DummyMainCreater.js +28 -15
  55. package/lib/core/common/EtsConst.d.ts +1 -0
  56. package/lib/core/common/EtsConst.d.ts.map +1 -1
  57. package/lib/core/common/EtsConst.js +2 -1
  58. package/lib/core/common/IRUtils.d.ts +6 -0
  59. package/lib/core/common/IRUtils.d.ts.map +1 -1
  60. package/lib/core/common/IRUtils.js +29 -2
  61. package/lib/core/common/ModelUtils.d.ts +1 -0
  62. package/lib/core/common/ModelUtils.d.ts.map +1 -1
  63. package/lib/core/common/ModelUtils.js +32 -32
  64. package/lib/core/common/TSConst.d.ts +10 -3
  65. package/lib/core/common/TSConst.d.ts.map +1 -1
  66. package/lib/core/common/TSConst.js +11 -4
  67. package/lib/core/common/TypeInference.d.ts +8 -2
  68. package/lib/core/common/TypeInference.d.ts.map +1 -1
  69. package/lib/core/common/TypeInference.js +218 -87
  70. package/lib/core/common/ValueUtil.d.ts +0 -4
  71. package/lib/core/common/ValueUtil.d.ts.map +1 -1
  72. package/lib/core/common/ValueUtil.js +8 -25
  73. package/lib/core/dataflow/DataflowSolver.d.ts.map +1 -1
  74. package/lib/core/dataflow/DataflowSolver.js +2 -4
  75. package/lib/core/dataflow/TiantAnalysis.js +2 -1
  76. package/lib/core/dataflow/Util.d.ts +1 -1
  77. package/lib/core/dataflow/Util.d.ts.map +1 -1
  78. package/lib/core/dataflow/Util.js +8 -7
  79. package/lib/core/graph/BasicBlock.d.ts +41 -0
  80. package/lib/core/graph/BasicBlock.d.ts.map +1 -1
  81. package/lib/core/graph/BasicBlock.js +132 -1
  82. package/lib/core/graph/Cfg.d.ts +30 -1
  83. package/lib/core/graph/Cfg.d.ts.map +1 -1
  84. package/lib/core/graph/Cfg.js +129 -6
  85. package/lib/core/graph/builder/ViewTreeBuilder.d.ts.map +1 -1
  86. package/lib/core/graph/builder/ViewTreeBuilder.js +3 -2
  87. package/lib/core/model/ArkBaseModel.d.ts +8 -0
  88. package/lib/core/model/ArkBaseModel.d.ts.map +1 -1
  89. package/lib/core/model/ArkBaseModel.js +55 -3
  90. package/lib/core/model/ArkClass.d.ts +36 -30
  91. package/lib/core/model/ArkClass.d.ts.map +1 -1
  92. package/lib/core/model/ArkClass.js +78 -39
  93. package/lib/core/model/ArkExport.d.ts +3 -0
  94. package/lib/core/model/ArkExport.d.ts.map +1 -1
  95. package/lib/core/model/ArkExport.js +10 -0
  96. package/lib/core/model/ArkField.d.ts +2 -0
  97. package/lib/core/model/ArkField.d.ts.map +1 -1
  98. package/lib/core/model/ArkField.js +3 -0
  99. package/lib/core/model/ArkFile.d.ts +4 -0
  100. package/lib/core/model/ArkFile.d.ts.map +1 -1
  101. package/lib/core/model/ArkFile.js +20 -0
  102. package/lib/core/model/ArkImport.d.ts +2 -0
  103. package/lib/core/model/ArkImport.d.ts.map +1 -1
  104. package/lib/core/model/ArkImport.js +3 -0
  105. package/lib/core/model/ArkMetadata.d.ts +20 -0
  106. package/lib/core/model/ArkMetadata.d.ts.map +1 -0
  107. package/lib/core/model/ArkMetadata.js +44 -0
  108. package/lib/core/model/ArkMethod.d.ts +156 -53
  109. package/lib/core/model/ArkMethod.d.ts.map +1 -1
  110. package/lib/core/model/ArkMethod.js +309 -54
  111. package/lib/core/model/ArkNamespace.d.ts +4 -0
  112. package/lib/core/model/ArkNamespace.d.ts.map +1 -1
  113. package/lib/core/model/ArkNamespace.js +13 -0
  114. package/lib/core/model/ArkSignature.d.ts +11 -5
  115. package/lib/core/model/ArkSignature.d.ts.map +1 -1
  116. package/lib/core/model/ArkSignature.js +38 -18
  117. package/lib/core/model/builder/ArkClassBuilder.d.ts +0 -1
  118. package/lib/core/model/builder/ArkClassBuilder.d.ts.map +1 -1
  119. package/lib/core/model/builder/ArkClassBuilder.js +9 -34
  120. package/lib/core/model/builder/ArkExportBuilder.d.ts.map +1 -1
  121. package/lib/core/model/builder/ArkExportBuilder.js +6 -1
  122. package/lib/core/model/builder/ArkFieldBuilder.d.ts.map +1 -1
  123. package/lib/core/model/builder/ArkFieldBuilder.js +3 -0
  124. package/lib/core/model/builder/ArkFileBuilder.js +1 -1
  125. package/lib/core/model/builder/ArkImportBuilder.d.ts +2 -1
  126. package/lib/core/model/builder/ArkImportBuilder.d.ts.map +1 -1
  127. package/lib/core/model/builder/ArkImportBuilder.js +12 -5
  128. package/lib/core/model/builder/ArkMethodBuilder.d.ts +2 -1
  129. package/lib/core/model/builder/ArkMethodBuilder.d.ts.map +1 -1
  130. package/lib/core/model/builder/ArkMethodBuilder.js +87 -47
  131. package/lib/core/model/builder/ArkNamespaceBuilder.d.ts.map +1 -1
  132. package/lib/core/model/builder/ArkNamespaceBuilder.js +2 -0
  133. package/lib/core/model/builder/builderUtils.d.ts.map +1 -1
  134. package/lib/core/model/builder/builderUtils.js +25 -2
  135. package/lib/save/source/SourceClass.d.ts.map +1 -1
  136. package/lib/save/source/SourceClass.js +4 -0
  137. package/lib/save/source/SourceField.d.ts.map +1 -1
  138. package/lib/save/source/SourceField.js +4 -0
  139. package/lib/save/source/SourceMethod.d.ts.map +1 -1
  140. package/lib/save/source/SourceMethod.js +7 -0
  141. package/lib/save/source/SourceModule.d.ts.map +1 -1
  142. package/lib/save/source/SourceModule.js +14 -9
  143. package/lib/save/source/SourceNamespace.d.ts.map +1 -1
  144. package/lib/save/source/SourceNamespace.js +4 -0
  145. package/lib/save/source/SourceStmt.d.ts.map +1 -1
  146. package/lib/save/source/SourceStmt.js +15 -3
  147. package/lib/save/source/SourceTransformer.d.ts +6 -0
  148. package/lib/save/source/SourceTransformer.d.ts.map +1 -1
  149. package/lib/save/source/SourceTransformer.js +72 -41
  150. package/lib/save/source/SourceUtils.d.ts.map +1 -1
  151. package/lib/save/source/SourceUtils.js +3 -2
  152. package/lib/transformer/StaticSingleAssignmentFormer.js +1 -1
  153. package/lib/utils/CfgStructualAnalysis.d.ts +1 -0
  154. package/lib/utils/CfgStructualAnalysis.d.ts.map +1 -1
  155. package/lib/utils/CfgStructualAnalysis.js +41 -7
  156. package/lib/utils/callGraphUtils.d.ts.map +1 -1
  157. package/lib/utils/callGraphUtils.js +7 -10
  158. package/lib/utils/crypto_utils.d.ts +6 -0
  159. package/lib/utils/crypto_utils.d.ts.map +1 -0
  160. package/lib/utils/crypto_utils.js +57 -0
  161. package/lib/utils/getAllFiles.d.ts +1 -1
  162. package/lib/utils/getAllFiles.d.ts.map +1 -1
  163. package/lib/utils/getAllFiles.js +4 -5
  164. package/package.json +3 -2
@@ -50,6 +50,8 @@ const Statistics_1 = require("../common/Statistics");
50
50
  const Context_1 = require("./Context");
51
51
  const Pag_1 = require("./Pag");
52
52
  const PtsDS_1 = require("./PtsDS");
53
+ const TSConst_1 = require("../../core/common/TSConst");
54
+ const Const_1 = require("../../core/common/Const");
53
55
  const logger = logger_1.default.getLogger(logger_1.LOG_MODULE_TYPE.ARKANALYZER, 'PTA');
54
56
  class CSFuncID {
55
57
  constructor(cid, fid) {
@@ -69,10 +71,15 @@ class PagBuilder {
69
71
  this.cid2ThisRefMap = new Map();
70
72
  this.cid2ThisLocalMap = new Map();
71
73
  this.sdkMethodReturnValueMap = new Map();
74
+ // record the SDK API param, and create fake Values
75
+ this.sdkMethodParamValueMap = new Map();
76
+ this.fakeSdkMethodParamDeclaringStmt = new Stmt_1.ArkAssignStmt(new Local_1.Local(""), new Local_1.Local(""));
72
77
  this.funcHandledThisRound = new Set();
73
78
  this.updatedNodesThisRound = new Map();
74
79
  this.singletonFuncMap = new Map();
80
+ this.globalThisValue = new Local_1.Local(TSConst_1.GLOBAL_THIS);
75
81
  this.storagePropertyMap = new Map();
82
+ this.externalScopeVariableMap = new Map();
76
83
  this.pag = p;
77
84
  this.cg = cg;
78
85
  this.funcPags = new Map;
@@ -105,6 +112,8 @@ class PagBuilder {
105
112
  this.buildFuncPagAndAddToWorklist(csFuncID);
106
113
  });
107
114
  this.handleReachable();
115
+ this.globalThisPagNode = this.getOrNewGlobalThisNode(-1);
116
+ this.pag.addPagEdge(this.globalThisPagNode, this.globalThisPagNode, Pag_1.PagEdgeKind.Copy);
108
117
  }
109
118
  handleReachable() {
110
119
  if (this.worklist.length === 0) {
@@ -130,18 +139,20 @@ class PagBuilder {
130
139
  if (this.funcPags.has(funcID)) {
131
140
  return false;
132
141
  }
133
- let fpag = new Pag_1.FuncPag();
134
142
  let arkMethod = this.cg.getArkMethodByFuncID(funcID);
135
143
  if (arkMethod == null) {
136
144
  return false;
137
145
  }
138
146
  let cfg = arkMethod.getCfg();
139
147
  if (!cfg) {
148
+ this.buildSDKFuncPag(funcID);
140
149
  return false;
141
150
  }
142
151
  logger.trace(`[build FuncPag] ${arkMethod.getSignature().toString()}`);
152
+ let fpag = new Pag_1.FuncPag();
143
153
  for (let stmt of cfg.getStmts()) {
144
154
  if (stmt instanceof Stmt_1.ArkAssignStmt) {
155
+ this.handleValueFromExternalScope(stmt.getRightOp(), funcID);
145
156
  // Add non-call edges
146
157
  let kind = this.getEdgeKindForAssignStmt(stmt);
147
158
  if (kind !== Pag_1.PagEdgeKind.Unknown) {
@@ -154,7 +165,13 @@ class PagBuilder {
154
165
  let cs = this.cg.getCallSiteByStmt(stmt);
155
166
  if (cs) {
156
167
  // direct call is already existing in CG
168
+ // TODO: API Invoke stmt has anonymous method param, how to add these param into callee
157
169
  fpag.addNormalCallSite(cs);
170
+ if (ivkExpr.getMethodSignature().getDeclaringClassSignature()
171
+ .getDeclaringFileSignature().getFileName() === Const_1.UNKNOWN_FILE_NAME) {
172
+ fpag.addUnknownCallSite(cs);
173
+ continue;
174
+ }
158
175
  }
159
176
  else {
160
177
  throw new Error('Can not find static callsite');
@@ -172,7 +189,14 @@ class PagBuilder {
172
189
  let cs = this.cg.getCallSiteByStmt(stmt);
173
190
  if (cs) {
174
191
  // direct call or constructor call is already existing in CG
175
- fpag.addNormalCallSite(cs);
192
+ // TODO: some ptr invoke stmt is recognized as Static invoke in tests/resources/callgraph/funPtrTest1/fnPtrTest4.ts
193
+ // TODO: instance invoke(ptr invoke)
194
+ if (this.cg.isUnknownMethod(cs.calleeFuncID)) {
195
+ fpag.addUnknownCallSite(cs);
196
+ }
197
+ else {
198
+ fpag.addNormalCallSite(cs);
199
+ }
176
200
  continue;
177
201
  }
178
202
  let dycs = this.cg.getDynCallsiteByStmt(stmt);
@@ -191,7 +215,30 @@ class PagBuilder {
191
215
  this.pagStat.numTotalFunction++;
192
216
  return true;
193
217
  }
218
+ /**
219
+ * will not create real funcPag, only create param values
220
+ */
221
+ buildSDKFuncPag(funcID) {
222
+ var _a;
223
+ // check if SDK method
224
+ let cgNode = this.cg.getNode(funcID);
225
+ if (!cgNode.isSdkMethod()) {
226
+ return;
227
+ }
228
+ let args = (_a = this.cg.getArkMethodByFuncID(funcID)) === null || _a === void 0 ? void 0 : _a.getParameters();
229
+ if (!args) {
230
+ return;
231
+ }
232
+ let paramArr = [];
233
+ args.forEach((arg) => {
234
+ let argInstance = new Local_1.Local(arg.getName(), arg.getType());
235
+ argInstance.setDeclaringStmt(this.fakeSdkMethodParamDeclaringStmt);
236
+ paramArr.push(argInstance);
237
+ });
238
+ this.sdkMethodParamValueMap.set(funcID, paramArr);
239
+ }
194
240
  buildPagFromFuncPag(funcID, cid) {
241
+ var _a;
195
242
  let funcPag = this.funcPags.get(funcID);
196
243
  if (funcPag === undefined) {
197
244
  return;
@@ -200,8 +247,13 @@ class PagBuilder {
200
247
  return;
201
248
  }
202
249
  this.addEdgesFromFuncPag(funcPag, cid);
250
+ let interFuncPag = (_a = this.interFuncPags) === null || _a === void 0 ? void 0 : _a.get(funcID);
251
+ if (interFuncPag) {
252
+ this.addEdgesFromInterFuncPag(interFuncPag, cid);
253
+ }
203
254
  this.addCallsEdgesFromFuncPag(funcPag, cid);
204
- this.addDynamicCallSite(funcPag);
255
+ this.addDynamicCallSite(funcPag, funcID);
256
+ this.addUnknownCallSite(funcPag, funcID);
205
257
  this.handledFunc.add(`${cid}-${funcID}`);
206
258
  }
207
259
  /// Add Pag Nodes and Edges in function
@@ -224,9 +276,9 @@ class PagBuilder {
224
276
  /// add Copy edges interprocedural
225
277
  addCallsEdgesFromFuncPag(funcPag, cid) {
226
278
  for (let cs of funcPag.getNormalCallSites()) {
279
+ let ivkExpr = cs.callStmt.getInvokeExpr();
227
280
  let calleeCid = this.ctx.getOrNewContext(cid, cs.calleeFuncID, true);
228
281
  let calleeCGNode = this.cg.getNode(cs.calleeFuncID);
229
- let ivkExpr = cs.callStmt.getInvokeExpr();
230
282
  // process the Storage API(Static)
231
283
  if (!this.processStorage(cs, calleeCGNode, cid)) {
232
284
  // If not Storage API, process normal edge
@@ -335,6 +387,9 @@ class PagBuilder {
335
387
  }
336
388
  }
337
389
  processStorageGet(cs, cid) {
390
+ if (!(cs.callStmt instanceof Stmt_1.ArkAssignStmt)) {
391
+ return;
392
+ }
338
393
  let leftOp = cs.callStmt.getLeftOp();
339
394
  let ivkExpr = cs.callStmt.getInvokeExpr();
340
395
  let propertyName;
@@ -368,7 +423,7 @@ class PagBuilder {
368
423
  }
369
424
  return undefined;
370
425
  }
371
- addDynamicCallSite(funcPag) {
426
+ addDynamicCallSite(funcPag, funcID) {
372
427
  // add dyn callsite in funcpag to base node
373
428
  for (let cs of funcPag.getDynamicCallSites()) {
374
429
  let invokeExpr = cs.callStmt.getInvokeExpr();
@@ -381,6 +436,13 @@ class PagBuilder {
381
436
  }
382
437
  // TODO: check base under different cid
383
438
  let baseNodeIDs = this.pag.getNodesByValue(base);
439
+ if (!baseNodeIDs) {
440
+ // bind the call site to export base
441
+ let interProceduralLocal = this.getSourceValueFromExternalScope(base, funcID);
442
+ if (interProceduralLocal) {
443
+ baseNodeIDs = this.pag.getNodesByValue(interProceduralLocal);
444
+ }
445
+ }
384
446
  if (!baseNodeIDs) {
385
447
  logger.warn(`[build dynamic call site] can not handle call site with base ${base.toString()}`);
386
448
  continue;
@@ -394,79 +456,111 @@ class PagBuilder {
394
456
  }
395
457
  }
396
458
  }
459
+ addUnknownCallSite(funcPag, funcID) {
460
+ var _a;
461
+ let method = this.cg.getArkMethodByFuncID(funcID);
462
+ if (!method) {
463
+ throw new Error(`can not find ArkMethod by FuncID ${funcID}`);
464
+ }
465
+ let locals = (_a = method.getBody()) === null || _a === void 0 ? void 0 : _a.getLocals();
466
+ funcPag.getUnknownCallSites().forEach((unknownCallSite) => {
467
+ var _a;
468
+ let calleeName = (_a = unknownCallSite.callStmt.getInvokeExpr()) === null || _a === void 0 ? void 0 : _a.getMethodSignature().getMethodSubSignature().getMethodName();
469
+ let base = locals.get(calleeName);
470
+ if (base) {
471
+ let baseNodeIDs = this.pag.getNodesByValue(base);
472
+ if (!baseNodeIDs) {
473
+ logger.warn(`[build dynamic call site] can not handle call site with base ${base.toString()}`);
474
+ return;
475
+ }
476
+ for (let nodeID of baseNodeIDs.values()) {
477
+ let node = this.pag.getNode(nodeID);
478
+ if (!(node instanceof Pag_1.PagLocalNode)) {
479
+ continue;
480
+ }
481
+ node.addRelatedUnknownCallSite(unknownCallSite);
482
+ }
483
+ }
484
+ });
485
+ }
397
486
  addDynamicCallEdge(cs, baseClassPTNode, cid) {
398
487
  let srcNodes = [];
399
488
  let ivkExpr = cs.callStmt.getInvokeExpr();
400
489
  let ptNode = this.pag.getNode(baseClassPTNode);
401
490
  let value = ptNode.getValue();
402
- let callee = this.getDynamicCallee(ptNode, value, ivkExpr, cs);
403
- if (!callee) {
404
- return srcNodes;
405
- }
406
- // get caller and callee CG node, add param and return value PAG edge
407
- let dstCGNode = this.cg.getCallGraphNodeByMethod(callee.getSignature());
408
- let callerNode = this.cg.getNode(cs.callerFuncID);
409
- if (!callerNode) {
410
- throw new Error("Can not get caller method node");
411
- }
412
- // update call graph
413
- // TODO: movo to cgbuilder
414
- this.cg.addDynamicCallEdge(callerNode.getID(), dstCGNode.getID(), cs.callStmt);
415
- if (!this.cg.detectReachable(dstCGNode.getID(), callerNode.getID())) {
416
- let calleeCid = this.ctx.getOrNewContext(cid, dstCGNode.getID(), true);
417
- let staticCS = new CallGraph_1.CallSite(cs.callStmt, cs.args, dstCGNode.getID(), cs.callerFuncID);
418
- let staticSrcNodes = this.addStaticPagCallEdge(staticCS, cid, calleeCid);
419
- srcNodes.push(...staticSrcNodes);
420
- // Pass base's pts to callee's this pointer
421
- if (!dstCGNode.getIsSdkMethod() && ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
422
- let srcBaseNode = this.addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, cs.callerFuncID);
423
- srcNodes.push(srcBaseNode);
491
+ let callees = this.getDynamicCallee(ptNode, value, ivkExpr, cs);
492
+ for (let callee of callees) {
493
+ if (!callee) {
494
+ continue;
495
+ }
496
+ // get caller and callee CG node, add param and return value PAG edge
497
+ let dstCGNode = this.cg.getCallGraphNodeByMethod(callee.getSignature());
498
+ let callerNode = this.cg.getNode(cs.callerFuncID);
499
+ if (!callerNode) {
500
+ throw new Error("Can not get caller method node");
501
+ }
502
+ // update call graph
503
+ // TODO: movo to cgbuilder
504
+ this.cg.addDynamicCallEdge(callerNode.getID(), dstCGNode.getID(), cs.callStmt);
505
+ if (!this.cg.detectReachable(dstCGNode.getID(), callerNode.getID())) {
506
+ let calleeCid = this.ctx.getOrNewContext(cid, dstCGNode.getID(), true);
507
+ let staticCS = new CallGraph_1.CallSite(cs.callStmt, cs.args, dstCGNode.getID(), cs.callerFuncID);
508
+ let staticSrcNodes = this.addStaticPagCallEdge(staticCS, cid, calleeCid);
509
+ srcNodes.push(...staticSrcNodes);
510
+ // Pass base's pts to callee's this pointer
511
+ if (!dstCGNode.isSdkMethod() && ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
512
+ let srcBaseNode = this.addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, cs.callerFuncID);
513
+ srcNodes.push(srcBaseNode);
514
+ }
424
515
  }
425
516
  }
426
517
  return srcNodes;
427
518
  }
428
519
  getDynamicCallee(ptNode, value, ivkExpr, cs) {
429
- let callee = null;
430
- let calleeName = ivkExpr.getMethodSignature().getMethodSubSignature().getMethodName();
520
+ let callee = [];
431
521
  if (ptNode instanceof Pag_1.PagFuncNode) {
432
522
  // function ptr invoke
433
- callee = this.scene.getMethod(ptNode.getMethod());
523
+ let tempCallee = this.scene.getMethod(ptNode.getMethod());
434
524
  if (!callee) {
435
- return null;
525
+ return callee;
436
526
  }
527
+ callee.push(tempCallee);
437
528
  }
438
529
  else {
530
+ let calleeName = ivkExpr.getMethodSignature().getMethodSubSignature().getMethodName();
439
531
  // instance method invoke
440
532
  if (!(value instanceof Expr_1.ArkNewExpr || value instanceof Expr_1.ArkNewArrayExpr)) {
441
- return null;
533
+ return callee;
442
534
  }
535
+ let tempCallee;
443
536
  // try to get callee by MethodSignature
444
537
  if (value instanceof Expr_1.ArkNewExpr) {
445
538
  // get class signature
446
539
  let clsSig = value.getType().getClassSignature();
447
540
  let cls;
448
541
  cls = this.scene.getClass(clsSig);
449
- while (!callee && cls) {
450
- callee = cls.getMethodWithName(calleeName);
542
+ while (!tempCallee && cls) {
543
+ tempCallee = cls.getMethodWithName(calleeName);
451
544
  cls = cls.getSuperClass();
452
545
  }
453
- if (!callee) {
454
- callee = this.scene.getMethod(ivkExpr.getMethodSignature());
455
- }
456
- }
457
- // try to get callee by anonymous method in param
458
- if (!callee) {
459
- // try to change callee to param anonymous method
460
- // TODO: anonymous method param and return value pointer pass
461
- let args = cs.args;
462
- if ((args === null || args === void 0 ? void 0 : args.length) === 1 && args[0].getType() instanceof Type_1.FunctionType) {
463
- callee = this.scene.getMethod(args[0].getType().getMethodSignature());
546
+ if (!tempCallee) {
547
+ tempCallee = this.scene.getMethod(ivkExpr.getMethodSignature());
464
548
  }
465
549
  }
466
- if (!callee) {
550
+ if (!tempCallee && cs.args) {
467
551
  // while pts has {o_1, o_2} and invoke expr represents a method that only {o_1} has
468
552
  // return empty node when {o_2} come in
469
- return null;
553
+ // try to get callee by anonymous method in param
554
+ for (let arg of cs.args) {
555
+ // TODO: anonymous method param and return value pointer pass
556
+ let argType = arg.getType();
557
+ if (argType instanceof Type_1.FunctionType) {
558
+ callee.push(this.scene.getMethod(argType.getMethodSignature()));
559
+ }
560
+ }
561
+ }
562
+ else if (tempCallee) {
563
+ callee.push(tempCallee);
470
564
  }
471
565
  }
472
566
  return callee;
@@ -566,7 +660,7 @@ class PagBuilder {
566
660
  addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, callerFunID) {
567
661
  var _a;
568
662
  if (!callee || !callee.getCfg()) {
569
- console.log("callee is null");
663
+ logger.error(`callee is null`);
570
664
  return -1;
571
665
  }
572
666
  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);
@@ -581,6 +675,14 @@ class PagBuilder {
581
675
  let srcBaseLocal = ivkExpr.getBase();
582
676
  srcBaseLocal = this.getRealThisLocal(srcBaseLocal, callerFunID);
583
677
  let srcNodeId = this.pag.hasCtxNode(cid, srcBaseLocal);
678
+ if (!srcNodeId) {
679
+ // this check is for export local and closure use
680
+ // replace the invoke base, because its origin base has no pag node
681
+ let interProceduralLocal = this.getSourceValueFromExternalScope(srcBaseLocal, callerFunID);
682
+ if (interProceduralLocal) {
683
+ srcNodeId = this.pag.hasCtxNode(cid, interProceduralLocal);
684
+ }
685
+ }
584
686
  if (!srcNodeId) {
585
687
  throw new Error('Can not get base node');
586
688
  }
@@ -605,31 +707,8 @@ class PagBuilder {
605
707
  // TODO: check if nodes need to delete
606
708
  return srcNodes;
607
709
  }
608
- if (calleeNode.getIsSdkMethod()) {
609
- let returnType = calleeMethod.getReturnType();
610
- // TODO: add new array type
611
- if (!(returnType instanceof Type_1.ClassType) || !(cs.callStmt instanceof Stmt_1.ArkAssignStmt)) {
612
- return srcNodes;
613
- }
614
- // check fake heap object exists or not
615
- let cidMap = this.sdkMethodReturnValueMap.get(calleeMethod);
616
- if (!cidMap) {
617
- cidMap = new Map();
618
- }
619
- let newExpr = cidMap.get(calleeCid);
620
- if (!newExpr) {
621
- if (returnType instanceof Type_1.ClassType) {
622
- newExpr = new Expr_1.ArkNewExpr(returnType);
623
- }
624
- // } else if (returnType instanceof ArrayType) {
625
- // TODO: check how to transform array type 2 newArrayExpr
626
- // }
627
- }
628
- cidMap.set(calleeCid, newExpr);
629
- this.sdkMethodReturnValueMap.set(calleeMethod, cidMap);
630
- let srcPagNode = this.getOrNewPagNode(calleeCid, newExpr);
631
- let dstPagNode = this.getOrNewPagNode(callerCid, cs.callStmt.getLeftOp(), cs.callStmt);
632
- this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Address, cs.callStmt);
710
+ if (calleeNode.isSdkMethod()) {
711
+ srcNodes.push(...this.addSDKMethodPagCallEdge(cs, callerCid, calleeCid));
633
712
  return srcNodes;
634
713
  }
635
714
  if (!calleeMethod.getCfg()) {
@@ -640,7 +719,6 @@ class PagBuilder {
640
719
  // callee cid will updated if callee is singleton
641
720
  calleeCid = calleeCS.cid;
642
721
  // TODO: getParameterInstances's performance is not good. Need to refactor
643
- //let params = calleeMethod.getParameterInstances();
644
722
  let params = calleeMethod.getCfg().getStmts()
645
723
  .filter(stmt => stmt instanceof Stmt_1.ArkAssignStmt && stmt.getRightOp() instanceof Ref_1.ArkParameterRef)
646
724
  .map(stmt => stmt.getRightOp());
@@ -651,7 +729,6 @@ class PagBuilder {
651
729
  let arg = (_b = cs.args) === null || _b === void 0 ? void 0 : _b.at(i);
652
730
  let param = params.at(i);
653
731
  // TODO: param type should be ArkParameterRef?
654
- //if (arg && param && param instanceof ArkParameterRef) {
655
732
  if (arg && param) {
656
733
  if (arg instanceof Constant_1.Constant) {
657
734
  continue;
@@ -685,7 +762,7 @@ class PagBuilder {
685
762
  continue;
686
763
  }
687
764
  else if (retValue instanceof Expr_1.AbstractExpr) {
688
- console.log(retValue);
765
+ logger.debug(retValue);
689
766
  continue;
690
767
  }
691
768
  else {
@@ -695,6 +772,86 @@ class PagBuilder {
695
772
  }
696
773
  return srcNodes;
697
774
  }
775
+ addSDKMethodPagCallEdge(cs, callerCid, calleeCid) {
776
+ let srcNodes = [];
777
+ let calleeNode = this.cg.getNode(cs.calleeFuncID);
778
+ let calleeMethod = this.scene.getMethod(calleeNode.getMethod());
779
+ if (!calleeMethod) {
780
+ return srcNodes;
781
+ }
782
+ if (!this.sdkMethodParamValueMap.has(calleeNode.getID())) {
783
+ this.buildSDKFuncPag(calleeNode.getID());
784
+ }
785
+ this.addSDKMethodReturnPagEdge(cs, callerCid, calleeCid, calleeMethod);
786
+ srcNodes.push(...this.addSDKMethodParamPagEdge(cs, callerCid, calleeCid, calleeNode.getID()));
787
+ return srcNodes;
788
+ }
789
+ addSDKMethodReturnPagEdge(cs, callerCid, calleeCid, calleeMethod) {
790
+ let returnType = calleeMethod.getReturnType();
791
+ if (!(returnType instanceof Type_1.ClassType) || !(cs.callStmt instanceof Stmt_1.ArkAssignStmt)) {
792
+ return;
793
+ }
794
+ // check fake heap object exists or not
795
+ let cidMap = this.sdkMethodReturnValueMap.get(calleeMethod);
796
+ if (!cidMap) {
797
+ cidMap = new Map();
798
+ }
799
+ let newExpr = cidMap.get(calleeCid);
800
+ if (!newExpr) {
801
+ if (returnType instanceof Type_1.ClassType) {
802
+ newExpr = new Expr_1.ArkNewExpr(returnType);
803
+ }
804
+ }
805
+ cidMap.set(calleeCid, newExpr);
806
+ this.sdkMethodReturnValueMap.set(calleeMethod, cidMap);
807
+ let srcPagNode = this.getOrNewPagNode(calleeCid, newExpr);
808
+ let dstPagNode = this.getOrNewPagNode(callerCid, cs.callStmt.getLeftOp(), cs.callStmt);
809
+ this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Address, cs.callStmt);
810
+ }
811
+ addSDKMethodParamPagEdge(cs, callerCid, calleeCid, funcID) {
812
+ var _a, _b;
813
+ let argNum = (_a = cs.args) === null || _a === void 0 ? void 0 : _a.length;
814
+ let srcNodes = [];
815
+ if (argNum) {
816
+ // add args to parameters edges
817
+ for (let i = 0; i < argNum; i++) {
818
+ let arg = (_b = cs.args) === null || _b === void 0 ? void 0 : _b.at(i);
819
+ let paramValue;
820
+ if (arg instanceof Local_1.Local && arg.getType() instanceof Type_1.FunctionType) {
821
+ // TODO: cannot find value
822
+ paramValue = this.sdkMethodParamValueMap.get(funcID)[i];
823
+ }
824
+ else {
825
+ continue;
826
+ }
827
+ if (arg && paramValue) {
828
+ // Get or create new PAG node for argument and parameter
829
+ let srcPagNode = this.getOrNewPagNode(callerCid, arg, cs.callStmt);
830
+ let dstPagNode = this.getOrNewPagNode(calleeCid, paramValue, cs.callStmt);
831
+ if (dstPagNode instanceof Pag_1.PagLocalNode) {
832
+ // set the fake param Value in PagLocalNode
833
+ /**
834
+ * TODO: !!!
835
+ * some API param is in the form of anonymous method:
836
+ * component/common.d.ts
837
+ * declare function animateTo(value: AnimateParam, event: () => void): void;
838
+ *
839
+ * this param fake Value will create PagFuncNode rather than PagLocalNode
840
+ * when this API is called, the anonymous method pointer will not be able to pass into the fake Value PagNode
841
+ */
842
+ dstPagNode.setSdkParam();
843
+ let sdkParamInvokeStmt = new Stmt_1.ArkInvokeStmt(new Expr_1.ArkPtrInvokeExpr(arg.getType().getMethodSignature(), paramValue, []));
844
+ // create new DynCallSite
845
+ let sdkParamCallSite = new CallGraph_1.DynCallSite(funcID, sdkParamInvokeStmt, undefined, undefined);
846
+ dstPagNode.addRelatedDynCallSite(sdkParamCallSite);
847
+ }
848
+ this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
849
+ srcNodes.push(srcPagNode.getID());
850
+ }
851
+ }
852
+ }
853
+ return srcNodes;
854
+ }
698
855
  getOrNewPagNode(cid, v, s) {
699
856
  if (v instanceof Ref_1.ArkThisRef) {
700
857
  return this.getOrNewThisRefNode(cid, v);
@@ -706,12 +863,14 @@ class PagBuilder {
706
863
  if (v.getName() === "this") {
707
864
  return this.getOrNewThisLoalNode(cid, v, s);
708
865
  }
709
- else if (v.getName() === Pag_1.GLOBAL_THIS && v.getDeclaringStmt() == null) {
866
+ else if (v.getName() === TSConst_1.GLOBAL_THIS && v.getDeclaringStmt() == null) {
710
867
  // globalThis node has no cid
711
- return this.getOrNewGlobalThisNode(0);
868
+ return this.getOrNewGlobalThisNode(-1);
712
869
  }
713
870
  }
714
- v = this.getRealInstanceRef(v);
871
+ if (v instanceof Ref_1.ArkInstanceFieldRef || v instanceof Ref_1.ArkStaticFieldRef) {
872
+ v = this.getRealInstanceRef(v);
873
+ }
715
874
  return this.pag.getOrNewNode(cid, v, s);
716
875
  }
717
876
  /**
@@ -820,7 +979,7 @@ class PagBuilder {
820
979
  let real;
821
980
  if (v instanceof Ref_1.ArkInstanceFieldRef) {
822
981
  base = v.getBase();
823
- if (base instanceof Local_1.Local && base.getName() === Pag_1.GLOBAL_THIS && base.getDeclaringStmt() == null) {
982
+ if (base instanceof Local_1.Local && base.getName() === TSConst_1.GLOBAL_THIS && base.getDeclaringStmt() == null) {
824
983
  // replace the base in fieldRef
825
984
  base = this.getGlobalThisValue();
826
985
  v.setBase(base);
@@ -924,8 +1083,7 @@ class PagBuilder {
924
1083
  return false;
925
1084
  }
926
1085
  getGlobalThisValue() {
927
- var _a;
928
- return (_a = this.globalThisValue) !== null && _a !== void 0 ? _a : new Local_1.Local(Pag_1.GLOBAL_THIS);
1086
+ return this.globalThisValue;
929
1087
  }
930
1088
  getEdgeKindForAssignStmt(stmt) {
931
1089
  if (this.stmtIsCreateAddressObj(stmt)) {
@@ -981,7 +1139,7 @@ class PagBuilder {
981
1139
  (lhOp instanceof Local_1.Local && ((rhOp instanceof Local_1.Local && rhOp.getType() instanceof Type_1.FunctionType &&
982
1140
  rhOp.getDeclaringStmt() === null) ||
983
1141
  (rhOp instanceof Ref_1.AbstractFieldRef && rhOp.getType() instanceof Type_1.FunctionType))) ||
984
- (rhOp instanceof Local_1.Local && rhOp.getName() === Pag_1.GLOBAL_THIS && rhOp.getDeclaringStmt() == null)) {
1142
+ (rhOp instanceof Local_1.Local && rhOp.getName() === TSConst_1.GLOBAL_THIS && rhOp.getDeclaringStmt() == null)) {
985
1143
  return true;
986
1144
  }
987
1145
  // TODO: add other Address Obj creation
@@ -1061,5 +1219,142 @@ class PagBuilder {
1061
1219
  getHandledFuncs() {
1062
1220
  return Array.from(this.funcPags.keys());
1063
1221
  }
1222
+ /**
1223
+ * build export edge in internal func pag
1224
+ * @param value: Value that need to check if it is from import/export
1225
+ * @param originValue: if Value if InstanceFieldRef, the base will be passed to `value` recursively,
1226
+ * fieldRef will be passed to `originValue`
1227
+ */
1228
+ handleValueFromExternalScope(value, funcID, originValue) {
1229
+ if (value instanceof Local_1.Local) {
1230
+ if (value.getDeclaringStmt()) {
1231
+ // not from external scope
1232
+ return;
1233
+ }
1234
+ if (!value.getType()) {
1235
+ return;
1236
+ }
1237
+ let srcLocal = this.getSourceValueFromExternalScope(value, funcID);
1238
+ if (srcLocal) {
1239
+ // if `value` is from field base, use origin value(fieldRef) instead
1240
+ this.addInterFuncEdge(srcLocal, originValue !== null && originValue !== void 0 ? originValue : value, funcID);
1241
+ }
1242
+ }
1243
+ else if (value instanceof Ref_1.ArkInstanceFieldRef) {
1244
+ let base = value.getBase();
1245
+ if (base) {
1246
+ this.handleValueFromExternalScope(base, funcID, value);
1247
+ }
1248
+ }
1249
+ }
1250
+ addInterFuncEdge(src, dst, funcID) {
1251
+ var _a, _b, _c;
1252
+ this.interFuncPags = (_a = this.interFuncPags) !== null && _a !== void 0 ? _a : new Map();
1253
+ let interFuncPag = (_b = this.interFuncPags.get(funcID)) !== null && _b !== void 0 ? _b : new Pag_1.InterFuncPag();
1254
+ // Export a local
1255
+ // Add a InterProcedural edge
1256
+ if (dst instanceof Local_1.Local) {
1257
+ let e = { src: src, dst: dst, kind: Pag_1.PagEdgeKind.InterProceduralCopy };
1258
+ interFuncPag.addToInterProceduralEdgeSet(e);
1259
+ this.addExportVariableMap(src, dst);
1260
+ }
1261
+ else if (dst instanceof Ref_1.ArkInstanceFieldRef) {
1262
+ // record the export base use
1263
+ this.addExportVariableMap(src, dst.getBase());
1264
+ }
1265
+ this.interFuncPags.set(funcID, interFuncPag);
1266
+ // Put the function which the src belongs to to worklist
1267
+ let srcFunc = (_c = src.getDeclaringStmt()) === null || _c === void 0 ? void 0 : _c.getCfg().getDeclaringMethod();
1268
+ if (srcFunc) {
1269
+ let srcFuncID = this.cg.getCallGraphNodeByMethod(srcFunc.getSignature()).getID();
1270
+ let cid = this.ctx.getNewContextID(srcFuncID);
1271
+ let csFuncID = new CSFuncID(cid, srcFuncID);
1272
+ this.buildFuncPagAndAddToWorklist(csFuncID);
1273
+ }
1274
+ // Extend other types of src here
1275
+ }
1276
+ getSourceValueFromExternalScope(value, funcID) {
1277
+ let sourceValue;
1278
+ // TODO: first from default method
1279
+ sourceValue = this.getDefaultMethodSourceValue(value, funcID);
1280
+ if (!sourceValue) {
1281
+ sourceValue = this.getExportSourceValue(value, funcID);
1282
+ }
1283
+ return sourceValue;
1284
+ }
1285
+ getDefaultMethodSourceValue(value, funcID) {
1286
+ var _a, _b, _c, _d, _e, _f, _g;
1287
+ // namespace check
1288
+ let arkMethod = this.cg.getArkMethodByFuncID(funcID);
1289
+ if (!arkMethod) {
1290
+ return;
1291
+ }
1292
+ let declaringNameSpace = arkMethod.getDeclaringArkClass().getDeclaringArkNamespace();
1293
+ while (declaringNameSpace) {
1294
+ let nameSpaceLocals = (_c = (_b = (_a = declaringNameSpace.getDefaultClass()
1295
+ .getDefaultArkMethod()) === null || _a === void 0 ? void 0 : _a.getBody()) === null || _b === void 0 ? void 0 : _b.getLocals()) !== null && _c !== void 0 ? _c : new Map();
1296
+ if (nameSpaceLocals.has(value.getName())) {
1297
+ return nameSpaceLocals.get(value.getName());
1298
+ }
1299
+ declaringNameSpace = (_d = declaringNameSpace.getDeclaringArkNamespace()) !== null && _d !== void 0 ? _d : undefined;
1300
+ }
1301
+ // file check
1302
+ let declaringFile = arkMethod.getDeclaringArkFile();
1303
+ let fileLocals = (_g = (_f = (_e = declaringFile.getDefaultClass()
1304
+ .getDefaultArkMethod()) === null || _e === void 0 ? void 0 : _e.getBody()) === null || _f === void 0 ? void 0 : _f.getLocals()) !== null && _g !== void 0 ? _g : new Map();
1305
+ if (!fileLocals.has(value.getName())) {
1306
+ return;
1307
+ }
1308
+ return fileLocals.get(value.getName());
1309
+ }
1310
+ getExportSourceValue(value, funcID) {
1311
+ let curMethod = this.cg.getArkMethodByFuncID(funcID);
1312
+ if (!curMethod) {
1313
+ return;
1314
+ }
1315
+ let curFile = curMethod.getDeclaringArkFile();
1316
+ let impInfo = curFile.getImportInfoBy(value.getName());
1317
+ if (!impInfo) {
1318
+ return;
1319
+ }
1320
+ let exportSource = impInfo.getLazyExportInfo();
1321
+ if (!exportSource) {
1322
+ return;
1323
+ }
1324
+ let exportSouceValue = exportSource.getArkExport();
1325
+ if (exportSouceValue instanceof Local_1.Local) {
1326
+ return exportSouceValue;
1327
+ }
1328
+ }
1329
+ addExportVariableMap(src, dst) {
1330
+ var _a;
1331
+ let exportMap = (_a = this.externalScopeVariableMap.get(src)) !== null && _a !== void 0 ? _a : [];
1332
+ if (!exportMap.includes(dst)) {
1333
+ exportMap.push(dst);
1334
+ this.externalScopeVariableMap.set(src, exportMap);
1335
+ }
1336
+ }
1337
+ getExportVariableMap(src) {
1338
+ var _a;
1339
+ return (_a = this.externalScopeVariableMap.get(src)) !== null && _a !== void 0 ? _a : [];
1340
+ }
1341
+ /// Add inter-procedural Pag Nodes and Edges
1342
+ addEdgesFromInterFuncPag(interFuncPag, cid) {
1343
+ let edges = interFuncPag.getInterProceduralEdges();
1344
+ if (edges.size === 0) {
1345
+ return false;
1346
+ }
1347
+ for (let e of edges) {
1348
+ // Existing local exported nodes -> ExportNode
1349
+ let exportLocal = e.src;
1350
+ let dstPagNode = this.getOrNewPagNode(cid, e.dst);
1351
+ // get export local node in all cid
1352
+ let existingNodes = this.pag.getNodesByValue(exportLocal);
1353
+ existingNodes === null || existingNodes === void 0 ? void 0 : existingNodes.forEach(n => {
1354
+ this.pag.addPagEdge(this.pag.getNode(n), dstPagNode, e.kind);
1355
+ });
1356
+ }
1357
+ return true;
1358
+ }
1064
1359
  }
1065
1360
  exports.PagBuilder = PagBuilder;