arkanalyzer 1.0.29 → 1.0.31

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 (86) hide show
  1. package/lib/Scene.d.ts +7 -0
  2. package/lib/Scene.d.ts.map +1 -1
  3. package/lib/Scene.js +196 -173
  4. package/lib/VFG/builder/DVFGBuilder.d.ts.map +1 -1
  5. package/lib/VFG/builder/DVFGBuilder.js +11 -6
  6. package/lib/callgraph/algorithm/AbstractAnalysis.d.ts +3 -1
  7. package/lib/callgraph/algorithm/AbstractAnalysis.d.ts.map +1 -1
  8. package/lib/callgraph/algorithm/AbstractAnalysis.js +18 -10
  9. package/lib/callgraph/algorithm/RapidTypeAnalysis.d.ts.map +1 -1
  10. package/lib/callgraph/algorithm/RapidTypeAnalysis.js +8 -7
  11. package/lib/callgraph/common/Statistics.d.ts.map +1 -1
  12. package/lib/callgraph/common/Statistics.js +25 -24
  13. package/lib/callgraph/model/CallGraph.d.ts.map +1 -1
  14. package/lib/callgraph/model/CallGraph.js +0 -1
  15. package/lib/callgraph/pointerAnalysis/Context.d.ts.map +1 -1
  16. package/lib/callgraph/pointerAnalysis/Context.js +0 -1
  17. package/lib/callgraph/pointerAnalysis/PTAUtils.d.ts +9 -3
  18. package/lib/callgraph/pointerAnalysis/PTAUtils.d.ts.map +1 -1
  19. package/lib/callgraph/pointerAnalysis/PTAUtils.js +32 -18
  20. package/lib/callgraph/pointerAnalysis/Pag.d.ts +17 -1
  21. package/lib/callgraph/pointerAnalysis/Pag.d.ts.map +1 -1
  22. package/lib/callgraph/pointerAnalysis/Pag.js +74 -27
  23. package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts +51 -18
  24. package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts.map +1 -1
  25. package/lib/callgraph/pointerAnalysis/PagBuilder.js +533 -346
  26. package/lib/callgraph/pointerAnalysis/PointerAnalysis.d.ts.map +1 -1
  27. package/lib/callgraph/pointerAnalysis/PointerAnalysis.js +15 -14
  28. package/lib/core/base/Local.js +2 -2
  29. package/lib/core/base/Type.d.ts +10 -1
  30. package/lib/core/base/Type.d.ts.map +1 -1
  31. package/lib/core/base/Type.js +18 -1
  32. package/lib/core/common/ArkValueTransformer.d.ts.map +1 -1
  33. package/lib/core/common/ArkValueTransformer.js +3 -1
  34. package/lib/core/common/DummyMainCreater.d.ts.map +1 -1
  35. package/lib/core/common/DummyMainCreater.js +17 -20
  36. package/lib/core/common/IRInference.d.ts.map +1 -1
  37. package/lib/core/common/IRInference.js +21 -12
  38. package/lib/core/common/TypeInference.d.ts +1 -0
  39. package/lib/core/common/TypeInference.d.ts.map +1 -1
  40. package/lib/core/common/TypeInference.js +30 -4
  41. package/lib/core/dataflow/DataflowSolver.d.ts +1 -0
  42. package/lib/core/dataflow/DataflowSolver.d.ts.map +1 -1
  43. package/lib/core/dataflow/DataflowSolver.js +21 -17
  44. package/lib/core/dataflow/ReachingDef.d.ts.map +1 -1
  45. package/lib/core/dataflow/ReachingDef.js +6 -0
  46. package/lib/core/dataflow/UndefinedVariable.d.ts.map +1 -1
  47. package/lib/core/dataflow/UndefinedVariable.js +0 -25
  48. package/lib/core/graph/Cfg.d.ts +1 -0
  49. package/lib/core/graph/Cfg.d.ts.map +1 -1
  50. package/lib/core/graph/Cfg.js +49 -45
  51. package/lib/core/graph/DominanceFinder.js +19 -19
  52. package/lib/core/graph/builder/ViewTreeBuilder.d.ts +1 -0
  53. package/lib/core/graph/builder/ViewTreeBuilder.d.ts.map +1 -1
  54. package/lib/core/graph/builder/ViewTreeBuilder.js +34 -31
  55. package/lib/core/model/ArkMethod.d.ts.map +1 -1
  56. package/lib/core/model/ArkMethod.js +13 -6
  57. package/lib/core/model/builder/builderUtils.d.ts.map +1 -1
  58. package/lib/core/model/builder/builderUtils.js +72 -63
  59. package/lib/save/serializeArkIR.d.ts.map +1 -1
  60. package/lib/save/serializeArkIR.js +11 -24
  61. package/lib/save/source/SourceBody.js +10 -10
  62. package/lib/save/source/SourceFilePrinter.d.ts +1 -0
  63. package/lib/save/source/SourceFilePrinter.d.ts.map +1 -1
  64. package/lib/save/source/SourceFilePrinter.js +11 -8
  65. package/lib/save/source/SourceNamespace.d.ts +1 -0
  66. package/lib/save/source/SourceNamespace.d.ts.map +1 -1
  67. package/lib/save/source/SourceNamespace.js +11 -8
  68. package/lib/save/source/SourceStmt.d.ts +1 -0
  69. package/lib/save/source/SourceStmt.d.ts.map +1 -1
  70. package/lib/save/source/SourceStmt.js +37 -35
  71. package/lib/save/source/SourceTransformer.d.ts +2 -0
  72. package/lib/save/source/SourceTransformer.d.ts.map +1 -1
  73. package/lib/save/source/SourceTransformer.js +64 -54
  74. package/lib/transformer/StaticSingleAssignmentFormer.d.ts +5 -0
  75. package/lib/transformer/StaticSingleAssignmentFormer.d.ts.map +1 -1
  76. package/lib/transformer/StaticSingleAssignmentFormer.js +119 -101
  77. package/lib/utils/CfgStructualAnalysis.d.ts +1 -0
  78. package/lib/utils/CfgStructualAnalysis.d.ts.map +1 -1
  79. package/lib/utils/CfgStructualAnalysis.js +28 -24
  80. package/lib/utils/FileUtils.d.ts.map +1 -1
  81. package/lib/utils/FileUtils.js +14 -12
  82. package/lib/utils/callGraphUtils.d.ts.map +1 -1
  83. package/lib/utils/callGraphUtils.js +26 -23
  84. package/lib/utils/entryMethodUtils.d.ts.map +1 -1
  85. package/lib/utils/entryMethodUtils.js +11 -8
  86. package/package.json +2 -2
@@ -81,6 +81,7 @@ class PagBuilder {
81
81
  this.globalThisValue = new Local_1.Local(TSConst_1.GLOBAL_THIS_NAME);
82
82
  this.storagePropertyMap = new Map();
83
83
  this.externalScopeVariableMap = new Map();
84
+ this.retriggerNodesList = new Set();
84
85
  this.pag = p;
85
86
  this.cg = cg;
86
87
  this.scale = scale;
@@ -154,9 +155,7 @@ class PagBuilder {
154
155
  let fpag = new Pag_1.FuncPag();
155
156
  for (let stmt of cfg.getStmts()) {
156
157
  if (stmt instanceof Stmt_1.ArkAssignStmt) {
157
- stmt.getRightOp().getUses().forEach((v) => {
158
- this.handleValueFromExternalScope(v, funcID);
159
- });
158
+ this.processExternalScopeValue(stmt.getRightOp(), funcID);
160
159
  // Add non-call edges
161
160
  let kind = this.getEdgeKindForAssignStmt(stmt);
162
161
  if (kind !== Pag_1.PagEdgeKind.Unknown) {
@@ -167,6 +166,7 @@ class PagBuilder {
167
166
  this.buildInvokeExprInAssignStmt(stmt, fpag);
168
167
  }
169
168
  else if (stmt instanceof Stmt_1.ArkInvokeStmt && this.scale === PointerAnalysisConfig_1.PtaAnalysisScale.WholeProgram) {
169
+ this.processExternalScopeValue(stmt.getInvokeExpr(), funcID);
170
170
  this.buildInvokeExprInInvokeStmt(stmt, fpag);
171
171
  }
172
172
  else {
@@ -235,6 +235,16 @@ class PagBuilder {
235
235
  throw new Error('Can not find callsite by stmt');
236
236
  }
237
237
  }
238
+ processExternalScopeValue(value, funcID) {
239
+ if (value instanceof Local_1.Local) {
240
+ this.handleValueFromExternalScope(value, funcID);
241
+ }
242
+ else if (value instanceof Expr_1.ArkInstanceInvokeExpr) {
243
+ value.getUses().forEach((v) => {
244
+ this.handleValueFromExternalScope(v, funcID);
245
+ });
246
+ }
247
+ }
238
248
  /**
239
249
  * will not create real funcPag, only create param values
240
250
  */
@@ -306,7 +316,7 @@ class PagBuilder {
306
316
  this.addEdgesFromInterFuncPag(interFuncPag, cid);
307
317
  }
308
318
  this.addCallsEdgesFromFuncPag(funcPag, cid);
309
- this.addDynamicCallSite(funcPag, funcID);
319
+ this.addDynamicCallSite(funcPag, funcID, cid);
310
320
  this.addUnknownCallSite(funcPag, funcID);
311
321
  this.handledFunc.add(`${cid}-${funcID}`);
312
322
  }
@@ -361,7 +371,7 @@ class PagBuilder {
361
371
  if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
362
372
  let baseNode = this.getOrNewPagNode(cid, ivkExpr.getBase());
363
373
  let baseNodeID = baseNode.getID();
364
- this.addThisRefCallEdge(baseNodeID, cid, ivkExpr, callee, calleeCid, cs.callerFuncID);
374
+ this.addThisRefCallEdge(baseNodeID, cid, ivkExpr.getBase(), callee, calleeCid, cs.callerFuncID);
365
375
  }
366
376
  else {
367
377
  logger.error(`constructor or intrinsic func is static ${ivkExpr.toString()}`);
@@ -370,130 +380,7 @@ class PagBuilder {
370
380
  }
371
381
  return true;
372
382
  }
373
- /**
374
- * process Storage API
375
- * @returns boolean: check if the cs represent a Storage API, no matter the API will success or fail
376
- */
377
- processStorage(cs, calleeCGNode, cid) {
378
- let storageName = calleeCGNode.getMethod().getDeclaringClassSignature().getClassName();
379
- let storageType = this.getStorageType(storageName, cs, cid);
380
- // TODO: add other storages
381
- if (storageType === Pag_1.StorageType.APP_STORAGE) {
382
- let calleeName = calleeCGNode.getMethod().getMethodSubSignature().getMethodName();
383
- // TODO: complete AppStorage API
384
- if (calleeName === 'setOrCreate') {
385
- this.processStorageSetOrCreate(cs, cid);
386
- }
387
- else if (calleeName === 'link') {
388
- this.processStorageLink(cs, cid);
389
- }
390
- else if (calleeName === 'prop') {
391
- this.processStorageProp(cs, cid);
392
- }
393
- else if (calleeName === 'set') {
394
- this.processStorageSet(cs, cid);
395
- }
396
- else if (calleeName === 'get') {
397
- this.processStorageGet(cs, cid);
398
- }
399
- return true;
400
- }
401
- else if (storageType === Pag_1.StorageType.LOCAL_STORAGE) {
402
- // TODO: LocalStorage is not Static
403
- }
404
- return false;
405
- }
406
- processStorageSetOrCreate(cs, cid) {
407
- let propertyStr = this.getPropertyName(cs.args[0]);
408
- if (!propertyStr) {
409
- return;
410
- }
411
- let propertyName = propertyStr;
412
- let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
413
- let storageObj = cs.args[1];
414
- this.addPropertyLinkEdge(propertyNode, storageObj, cid, cs.callStmt, Pag_1.StorageLinkEdgeType.Local2Property);
415
- }
416
- processStorageLink(cs, cid) {
417
- let propertyStr = this.getPropertyName(cs.args[0]);
418
- if (!propertyStr) {
419
- return;
420
- }
421
- let propertyName = propertyStr;
422
- let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
423
- let leftOp = cs.callStmt.getLeftOp();
424
- let linkedOpNode = this.pag.getOrNewNode(cid, leftOp);
425
- if (linkedOpNode instanceof Pag_1.PagLocalNode) {
426
- linkedOpNode.setStorageLink(Pag_1.StorageType.APP_STORAGE, propertyName);
427
- }
428
- this.pag.addPagEdge(propertyNode, linkedOpNode, Pag_1.PagEdgeKind.Copy);
429
- this.pag.addPagEdge(linkedOpNode, propertyNode, Pag_1.PagEdgeKind.Copy);
430
- }
431
- processStorageProp(cs, cid) {
432
- let propertyStr = this.getPropertyName(cs.args[0]);
433
- if (!propertyStr) {
434
- return;
435
- }
436
- let propertyName = propertyStr;
437
- let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
438
- let leftOp = cs.callStmt.getLeftOp();
439
- let linkedOpNode = this.pag.getOrNewNode(cid, leftOp);
440
- if (linkedOpNode instanceof Pag_1.PagLocalNode) {
441
- linkedOpNode.setStorageLink(Pag_1.StorageType.APP_STORAGE, propertyName);
442
- }
443
- this.pag.addPagEdge(propertyNode, linkedOpNode, Pag_1.PagEdgeKind.Copy);
444
- }
445
- processStorageSet(cs, cid) {
446
- let ivkExpr = cs.callStmt.getInvokeExpr();
447
- if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
448
- let base = ivkExpr.getBase();
449
- let baseNode = this.pag.getOrNewNode(cid, base);
450
- if (baseNode.isStorageLinked()) {
451
- let argsNode = this.pag.getOrNewNode(cid, cs.args[0]);
452
- this.pag.addPagEdge(argsNode, baseNode, Pag_1.PagEdgeKind.Copy);
453
- }
454
- }
455
- else if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
456
- // TODO: process AppStorage.set()
457
- }
458
- }
459
- processStorageGet(cs, cid) {
460
- if (!(cs.callStmt instanceof Stmt_1.ArkAssignStmt)) {
461
- return;
462
- }
463
- let leftOp = cs.callStmt.getLeftOp();
464
- let ivkExpr = cs.callStmt.getInvokeExpr();
465
- let propertyName;
466
- if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
467
- let propertyStr = this.getPropertyName(cs.args[0]);
468
- if (propertyStr) {
469
- propertyName = propertyStr;
470
- }
471
- }
472
- else if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
473
- let baseNode = this.pag.getOrNewNode(cid, ivkExpr.getBase());
474
- if (baseNode.isStorageLinked()) {
475
- propertyName = baseNode.getStorage().PropertyName;
476
- }
477
- }
478
- let propertyNode = this.getPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
479
- if (!propertyNode) {
480
- return;
481
- }
482
- this.pag.addPagEdge(propertyNode, this.pag.getOrNewNode(cid, leftOp, cs.callStmt), Pag_1.PagEdgeKind.Copy, cs.callStmt);
483
- }
484
- getPropertyName(value) {
485
- if (value instanceof Local_1.Local) {
486
- let type = value.getType();
487
- if (type instanceof Type_1.StringType) {
488
- return type.getName();
489
- }
490
- }
491
- else if (value instanceof Constant_1.Constant) {
492
- return value.getValue();
493
- }
494
- return undefined;
495
- }
496
- addDynamicCallSite(funcPag, funcID) {
383
+ addDynamicCallSite(funcPag, funcID, cid) {
497
384
  // add dyn callsite in funcpag to base node
498
385
  for (let cs of funcPag.getDynamicCallSites()) {
499
386
  let invokeExpr = cs.callStmt.getInvokeExpr();
@@ -524,6 +411,9 @@ class PagBuilder {
524
411
  }
525
412
  node.addRelatedDynCallSite(cs);
526
413
  }
414
+ if (cs.callStmt instanceof Stmt_1.ArkAssignStmt) {
415
+ this.getOrNewPagNode(cid, cs.callStmt.getLeftOp(), cs.callStmt);
416
+ }
527
417
  }
528
418
  }
529
419
  addUnknownCallSite(funcPag, funcID) {
@@ -537,19 +427,20 @@ class PagBuilder {
537
427
  var _a;
538
428
  let calleeName = (_a = unknownCallSite.callStmt.getInvokeExpr()) === null || _a === void 0 ? void 0 : _a.getMethodSignature().getMethodSubSignature().getMethodName();
539
429
  let base = locals.get(calleeName);
540
- if (base) {
541
- let baseNodeIDs = this.pag.getNodesByValue(base);
542
- if (!baseNodeIDs) {
543
- logger.warn(`[build dynamic call site] can not handle call site with base ${base.toString()}`);
544
- return;
545
- }
546
- for (let nodeID of baseNodeIDs.values()) {
547
- let node = this.pag.getNode(nodeID);
548
- if (!(node instanceof Pag_1.PagLocalNode)) {
549
- continue;
550
- }
551
- node.addRelatedUnknownCallSite(unknownCallSite);
430
+ if (!base) {
431
+ return;
432
+ }
433
+ let baseNodeIDs = this.pag.getNodesByValue(base);
434
+ if (!baseNodeIDs) {
435
+ logger.warn(`[build dynamic call site] can not handle call site with base ${base.toString()}`);
436
+ return;
437
+ }
438
+ for (let nodeID of baseNodeIDs.values()) {
439
+ let node = this.pag.getNode(nodeID);
440
+ if (!(node instanceof Pag_1.PagLocalNode)) {
441
+ continue;
552
442
  }
443
+ node.addRelatedUnknownCallSite(unknownCallSite);
553
444
  }
554
445
  });
555
446
  }
@@ -572,24 +463,29 @@ class PagBuilder {
572
463
  // update call graph
573
464
  // TODO: movo to cgbuilder
574
465
  this.cg.addDynamicCallEdge(callerNode.getID(), dstCGNode.getID(), cs.callStmt);
575
- if (!this.cg.detectReachable(dstCGNode.getID(), callerNode.getID())) {
576
- let calleeCid = this.ctx.getOrNewContext(cid, dstCGNode.getID(), true);
577
- let staticCS = new CallGraph_1.CallSite(cs.callStmt, cs.args, dstCGNode.getID(), cs.callerFuncID);
578
- if (this.scale === PointerAnalysisConfig_1.PtaAnalysisScale.MethodLevel) {
579
- srcNodes.push(...this.addStaticPagCallReturnEdge(staticCS, baseClassPTNode, calleeCid));
580
- continue;
581
- }
582
- srcNodes.push(...this.processContainerPagCallEdge(staticCS, cid, baseClassPTNode));
583
- srcNodes.push(...this.addStaticPagCallEdge(staticCS, cid, calleeCid));
584
- // Pass base's pts to callee's this pointer
585
- if (!dstCGNode.isSdkMethod() && ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
586
- let srcBaseNode = this.addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, cs.callerFuncID);
587
- srcNodes.push(srcBaseNode);
588
- }
466
+ if (this.cg.detectReachable(dstCGNode.getID(), callerNode.getID())) {
467
+ return srcNodes;
468
+ }
469
+ let calleeCid = this.ctx.getOrNewContext(cid, dstCGNode.getID(), true);
470
+ let staticCS = new CallGraph_1.CallSite(cs.callStmt, cs.args, dstCGNode.getID(), cs.callerFuncID);
471
+ if (this.scale === PointerAnalysisConfig_1.PtaAnalysisScale.MethodLevel) {
472
+ srcNodes.push(...this.addStaticPagCallReturnEdge(staticCS, baseClassPTNode, calleeCid));
473
+ continue;
474
+ }
475
+ if ((0, PTAUtils_1.getBuiltInApiType)(ivkExpr === null || ivkExpr === void 0 ? void 0 : ivkExpr.getMethodSignature()) === PTAUtils_1.BuiltApiType.NotBuiltIn) {
476
+ srcNodes.push(...this.processNormalMethodPagCallEdge(staticCS, cid, calleeCid, baseClassPTNode));
477
+ }
478
+ else {
479
+ // special SDK call: Container API, Function API
480
+ srcNodes.push(...this.processBuiltInMethodPagCallEdge(staticCS, cid, calleeCid, baseClassPTNode));
589
481
  }
590
482
  }
591
483
  return srcNodes;
592
484
  }
485
+ /**
486
+ * all possible callee methods of a dynamic call site
487
+ * handle both PtrInvokeExpr and InstanceInvokeExpr
488
+ */
593
489
  getDynamicCallee(ptNode, value, ivkExpr, cs) {
594
490
  let callee = [];
595
491
  if (ptNode instanceof Pag_1.PagFuncNode) {
@@ -599,58 +495,183 @@ class PagBuilder {
599
495
  return callee;
600
496
  }
601
497
  callee.push(tempCallee);
602
- }
603
- else {
604
- let calleeName = ivkExpr.getMethodSignature().getMethodSubSignature().getMethodName();
605
- // instance method invoke
606
- if (!(value instanceof Expr_1.ArkNewExpr || value instanceof Expr_1.ArkNewArrayExpr)) {
607
- return callee;
608
- }
609
- let tempCallee;
610
- // try to get callee by MethodSignature
611
- if (value instanceof Expr_1.ArkNewExpr) {
612
- // get class signature
613
- let clsSig = value.getType().getClassSignature();
614
- let cls;
615
- cls = this.scene.getClass(clsSig);
616
- while (!tempCallee && cls) {
617
- tempCallee = cls.getMethodWithName(calleeName);
618
- cls = cls.getSuperClass();
619
- }
620
- if (!tempCallee) {
621
- tempCallee = this.scene.getMethod(ivkExpr.getMethodSignature());
498
+ return callee;
499
+ }
500
+ //else branch
501
+ let calleeName = ivkExpr.getMethodSignature().getMethodSubSignature().getMethodName();
502
+ // instance method invoke
503
+ if (!(value instanceof Expr_1.ArkNewExpr || value instanceof Expr_1.ArkNewArrayExpr)) {
504
+ return callee;
505
+ }
506
+ let tempCallee;
507
+ // try to get callee by MethodSignature
508
+ if (value instanceof Expr_1.ArkNewExpr) {
509
+ // get class signature
510
+ let clsSig = value.getType().getClassSignature();
511
+ let cls;
512
+ cls = this.scene.getClass(clsSig);
513
+ while (!tempCallee && cls) {
514
+ tempCallee = cls.getMethodWithName(calleeName);
515
+ cls = cls.getSuperClass();
516
+ }
517
+ if (!tempCallee) {
518
+ tempCallee = this.scene.getMethod(ivkExpr.getMethodSignature());
519
+ }
520
+ }
521
+ if (!tempCallee && cs.args) {
522
+ // while pts has {o_1, o_2} and invoke expr represents a method that only {o_1} has
523
+ // return empty node when {o_2} come in
524
+ // try to get callee by anonymous method in param
525
+ for (let arg of cs.args) {
526
+ // TODO: anonymous method param and return value pointer pass
527
+ let argType = arg.getType();
528
+ if (argType instanceof Type_1.FunctionType) {
529
+ callee.push(this.scene.getMethod(argType.getMethodSignature()));
622
530
  }
623
531
  }
624
- if (!tempCallee && cs.args) {
625
- // while pts has {o_1, o_2} and invoke expr represents a method that only {o_1} has
626
- // return empty node when {o_2} come in
627
- // try to get callee by anonymous method in param
628
- for (let arg of cs.args) {
629
- // TODO: anonymous method param and return value pointer pass
630
- let argType = arg.getType();
631
- if (argType instanceof Type_1.FunctionType) {
632
- callee.push(this.scene.getMethod(argType.getMethodSignature()));
633
- }
634
- }
532
+ }
533
+ else if (tempCallee) {
534
+ callee.push(tempCallee);
535
+ }
536
+ return callee;
537
+ }
538
+ processNormalMethodPagCallEdge(staticCS, cid, calleeCid, baseClassPTNode) {
539
+ let srcNodes = [];
540
+ let ivkExpr = staticCS.callStmt.getInvokeExpr();
541
+ let ptNode = this.pag.getNode(baseClassPTNode);
542
+ let dstCGNode = this.cg.getNode(staticCS.calleeFuncID);
543
+ let callee = this.cg.getArkMethodByFuncID(staticCS.calleeFuncID);
544
+ // Dynamic call, Ptr call, normal SDK call
545
+ srcNodes.push(...this.addStaticPagCallEdge(staticCS, cid, calleeCid, ptNode));
546
+ // Pass base's pts to callee's this pointer
547
+ if (!dstCGNode.isSdkMethod() && ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
548
+ let srcBaseNode = this.addThisRefCallEdge(baseClassPTNode, cid, ivkExpr.getBase(), callee, calleeCid, staticCS.callerFuncID);
549
+ srcNodes.push(srcBaseNode);
550
+ }
551
+ else if (!dstCGNode.isSdkMethod() && ivkExpr instanceof Expr_1.ArkPtrInvokeExpr) {
552
+ let thisValue = ptNode.getCS().args[0];
553
+ if (!(thisValue instanceof Local_1.Local)) {
554
+ return srcNodes;
635
555
  }
636
- else if (tempCallee) {
637
- callee.push(tempCallee);
556
+ this.addThisRefCallEdge(baseClassPTNode, ptNode.getOriginCid(), thisValue, callee, calleeCid, staticCS.callerFuncID);
557
+ }
558
+ return srcNodes;
559
+ }
560
+ /**
561
+ * include container API, Function API
562
+ */
563
+ processBuiltInMethodPagCallEdge(staticCS, cid, calleeCid, baseClassPTNode) {
564
+ let srcNodes = [];
565
+ let ivkExpr = staticCS.callStmt.getInvokeExpr();
566
+ let callee = this.scene.getMethod(ivkExpr.getMethodSignature());
567
+ let realCallee = this.cg.getArkMethodByFuncID(staticCS.calleeFuncID);
568
+ if (!callee) {
569
+ return srcNodes;
570
+ }
571
+ let builtInType = (0, PTAUtils_1.getBuiltInApiType)(callee.getSignature());
572
+ if (builtInType === PTAUtils_1.BuiltApiType.NotBuiltIn || !realCallee) {
573
+ return srcNodes;
574
+ }
575
+ switch (builtInType) {
576
+ case PTAUtils_1.BuiltApiType.SetAdd:
577
+ case PTAUtils_1.BuiltApiType.MapSet:
578
+ this.processContainerPagCallEdge(staticCS, cid, baseClassPTNode, builtInType);
579
+ break;
580
+ case PTAUtils_1.BuiltApiType.FunctionCall:
581
+ /**
582
+ * set this and param
583
+ * function.call(thisArg, arg1, arg2, ...)
584
+ */
585
+ this.handleFunctionCall(staticCS, cid, calleeCid, realCallee, srcNodes, baseClassPTNode);
586
+ break;
587
+ case PTAUtils_1.BuiltApiType.FunctionApply:
588
+ /**
589
+ * set this, resolve array param
590
+ * function.apply(thisArg, [argsArray])
591
+ */
592
+ this.handleFunctionApply(staticCS, cid, calleeCid, realCallee, srcNodes, baseClassPTNode);
593
+ break;
594
+ case PTAUtils_1.BuiltApiType.FunctionBind:
595
+ /**
596
+ * clone the function node and add the this pointer, origin callsite, args offset to it
597
+ * let f = function.bind(thisArg, arg1, arg2, ...)
598
+ * f();
599
+ */
600
+ this.handleFunctionBind(staticCS, cid, baseClassPTNode, srcNodes);
601
+ break;
602
+ }
603
+ return srcNodes;
604
+ }
605
+ processContainerPagCallEdge(cs, cid, baseClassPTNode, type) {
606
+ let srcNodes = [];
607
+ let calleeNode = this.cg.getNode(cs.calleeFuncID);
608
+ let calleeMethod = this.scene.getMethod(calleeNode.getMethod());
609
+ let ptNode = this.pag.getNode(baseClassPTNode);
610
+ if (!calleeMethod || !(ptNode instanceof Pag_1.PagNewContainerExprNode)) {
611
+ return srcNodes;
612
+ }
613
+ let containerValue = cs.callStmt.getInvokeExpr().getBase();
614
+ const containerValueProcess = (argIndex) => {
615
+ let srcNode = this.pag.getOrNewNode(cid, cs.args[argIndex], cs.callStmt);
616
+ let realContainerFieldPagNode = this.pag.getOrClonePagContainerFieldNode(baseClassPTNode, undefined, containerValue);
617
+ if (realContainerFieldPagNode) {
618
+ // In some cases, the value of a variable of array type may not be an explicit array object,
619
+ // and the value of `realContainerFieldPagNode` will be undefined.
620
+ this.pag.addPagEdge(srcNode, realContainerFieldPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
621
+ srcNodes.push(srcNode.getID());
638
622
  }
623
+ };
624
+ if (type === PTAUtils_1.BuiltApiType.SetAdd) {
625
+ containerValueProcess(0);
639
626
  }
640
- return callee;
627
+ else if (type === PTAUtils_1.BuiltApiType.MapSet) {
628
+ containerValueProcess(1);
629
+ }
630
+ return srcNodes;
641
631
  }
642
- addUpdatedNode(nodeID, diffPT) {
643
- var _a;
644
- let ptaConfig = PointerAnalysisConfig_1.PointerAnalysisConfig.getInstance();
645
- let updatedNode = (_a = this.updatedNodesThisRound.get(nodeID)) !== null && _a !== void 0 ? _a : new ptaConfig.ptsCollectionCtor();
646
- updatedNode.union(diffPT);
647
- this.updatedNodesThisRound.set(nodeID, updatedNode);
632
+ handleFunctionCall(staticCS, cid, calleeCid, realCallee, srcNodes, baseClassPTNode) {
633
+ this.buildFuncPagAndAddToWorklist(new CSFuncID(calleeCid, staticCS.calleeFuncID));
634
+ srcNodes.push(...this.addCallParamPagEdge(realCallee, staticCS.args, staticCS.callStmt, cid, calleeCid, 1));
635
+ this.addThisEdge(staticCS, cid, realCallee, srcNodes, baseClassPTNode, calleeCid);
648
636
  }
649
- getUpdatedNodes() {
650
- return this.updatedNodesThisRound;
637
+ handleFunctionApply(staticCS, cid, calleeCid, realCallee, srcNodes, baseClassPTNode) {
638
+ this.buildFuncPagAndAddToWorklist(new CSFuncID(calleeCid, staticCS.calleeFuncID));
639
+ let callerMethod = this.cg.getArkMethodByFuncID(staticCS.callerFuncID);
640
+ if (!callerMethod) {
641
+ throw new Error('Cannot get caller method');
642
+ }
643
+ let argsRealValues = this.transferArrayValues(callerMethod, staticCS.args[1]);
644
+ srcNodes.push(...this.addCallParamPagEdge(realCallee, argsRealValues, staticCS.callStmt, cid, calleeCid, 0));
645
+ this.addThisEdge(staticCS, cid, realCallee, srcNodes, baseClassPTNode, calleeCid);
651
646
  }
652
- resetUpdatedNodes() {
653
- this.updatedNodesThisRound.clear();
647
+ handleFunctionBind(staticCS, cid, baseClassPTNode, srcNodes) {
648
+ let srcNode = this.pag.getOrClonePagFuncNode(baseClassPTNode);
649
+ if (!srcNode) {
650
+ return;
651
+ }
652
+ this.setFunctionThisPt(staticCS, srcNode, cid);
653
+ let dstNode = this.getOrNewPagNode(cid, staticCS.callStmt.getLeftOp());
654
+ this.pag.addPagEdge(srcNode, dstNode, Pag_1.PagEdgeKind.Copy, staticCS.callStmt);
655
+ srcNodes.push(srcNode.getID());
656
+ srcNode.setCS(staticCS);
657
+ srcNode.setArgsOffset(1);
658
+ srcNode.setOriginCid(cid);
659
+ }
660
+ addThisEdge(staticCS, cid, realCallee, srcNodes, baseClassPTNode, calleeCid) {
661
+ if (!(staticCS.args[0] instanceof Constant_1.NullConstant) && !(realCallee.isStatic())) {
662
+ srcNodes.push(this.addThisRefCallEdge(baseClassPTNode, cid, staticCS.args[0], realCallee, calleeCid, staticCS.callerFuncID));
663
+ }
664
+ }
665
+ setFunctionThisPt(staticCS, srcNode, cid) {
666
+ let thisLocal = staticCS.args[0];
667
+ if (!(thisLocal instanceof Local_1.Local)) {
668
+ return;
669
+ }
670
+ let thisInstanceLocal = this.getRealThisLocal(thisLocal, staticCS.callerFuncID);
671
+ let baseThisNode = this.pag.getOrNewNode(cid, thisInstanceLocal);
672
+ for (let pt of baseThisNode.getPointTo()) {
673
+ srcNode.setThisPt(pt);
674
+ }
654
675
  }
655
676
  handleUnkownDynamicCall(cs, cid) {
656
677
  var _a;
@@ -664,11 +685,12 @@ class PagBuilder {
664
685
  callee = this.scene.getMethod(ivkExpr.getMethodSignature());
665
686
  if (!callee) {
666
687
  (_a = cs.args) === null || _a === void 0 ? void 0 : _a.forEach(arg => {
667
- if (arg.getType() instanceof Type_1.FunctionType) {
668
- callee = this.scene.getMethod(arg.getType().getMethodSignature());
669
- if (callee) {
670
- callees.push(callee);
671
- }
688
+ if (!(arg.getType() instanceof Type_1.FunctionType)) {
689
+ return;
690
+ }
691
+ callee = this.scene.getMethod(arg.getType().getMethodSignature());
692
+ if (callee) {
693
+ callees.push(callee);
672
694
  }
673
695
  });
674
696
  }
@@ -732,22 +754,10 @@ class PagBuilder {
732
754
  }
733
755
  return reAnalyzeNodes;
734
756
  }
735
- addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, callerFunID) {
736
- var _a;
737
- if (!callee || !callee.getCfg()) {
738
- logger.error(`callee is null`);
739
- return -1;
740
- }
741
- 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);
742
- let thisPtr = (thisAssignStmt === null || thisAssignStmt === void 0 ? void 0 : thisAssignStmt.at(0)).getRightOp();
743
- if (!thisPtr) {
744
- throw new Error('Can not get this ptr');
745
- }
746
- // IMPORTANT: set cid 2 base Pt info firstly
747
- this.cid2ThisRefPtMap.set(calleeCid, baseClassPTNode);
748
- let thisRefNode = this.getOrNewThisRefNode(calleeCid, thisPtr);
749
- thisRefNode.addPTNode(baseClassPTNode);
750
- let srcBaseLocal = ivkExpr.getBase();
757
+ addThisRefCallEdge(baseClassPTNode, cid, baseLocal, callee, calleeCid, callerFunID) {
758
+ let thisRefNodeID = this.recordThisRefNode(baseClassPTNode, callee, calleeCid);
759
+ let thisRefNode = this.pag.getNode(thisRefNodeID);
760
+ let srcBaseLocal = baseLocal;
751
761
  srcBaseLocal = this.getRealThisLocal(srcBaseLocal, callerFunID);
752
762
  let srcNodeId = this.pag.hasCtxNode(cid, srcBaseLocal);
753
763
  if (!srcNodeId) {
@@ -764,12 +774,30 @@ class PagBuilder {
764
774
  this.pag.addPagEdge(this.pag.getNode(srcNodeId), thisRefNode, Pag_1.PagEdgeKind.This);
765
775
  return srcNodeId;
766
776
  }
777
+ recordThisRefNode(baseClassPTNode, callee, calleeCid) {
778
+ var _a;
779
+ if (!callee || !callee.getCfg()) {
780
+ logger.error(`callee is null`);
781
+ return -1;
782
+ }
783
+ 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);
784
+ let thisPtr = (thisAssignStmt === null || thisAssignStmt === void 0 ? void 0 : thisAssignStmt.at(0)).getRightOp();
785
+ if (!thisPtr) {
786
+ throw new Error('Can not get this ptr');
787
+ }
788
+ // IMPORTANT: set cid 2 base Pt info firstly
789
+ this.cid2ThisRefPtMap.set(calleeCid, baseClassPTNode);
790
+ let thisRefNode = this.getOrNewThisRefNode(calleeCid, thisPtr);
791
+ thisRefNode.addPTNode(baseClassPTNode);
792
+ return thisRefNode.getID();
793
+ }
767
794
  /*
768
795
  * Add copy edges from arguments to parameters
769
796
  * ret edges from return values to callsite
770
797
  * Return src node
771
798
  */
772
- addStaticPagCallEdge(cs, callerCid, calleeCid) {
799
+ addStaticPagCallEdge(cs, callerCid, calleeCid, ptNode) {
800
+ var _a, _b, _c, _d;
773
801
  if (!calleeCid) {
774
802
  calleeCid = this.ctx.getOrNewContext(callerCid, cs.calleeFuncID, true);
775
803
  }
@@ -792,21 +820,100 @@ class PagBuilder {
792
820
  let calleeCS = this.buildFuncPagAndAddToWorklist(new CSFuncID(calleeCid, cs.calleeFuncID));
793
821
  // callee cid will updated if callee is singleton
794
822
  calleeCid = calleeCS.cid;
795
- // TODO: getParameterInstances's performance is not good. Need to refactor
823
+ let realArgs = (_a = cs.args) !== null && _a !== void 0 ? _a : [];
824
+ let argsOffset = 0;
825
+ if (ptNode && ptNode instanceof Pag_1.PagFuncNode && ptNode.getCS()) {
826
+ // for ptr invoke cloned by Function.bind()
827
+ realArgs = (_b = ptNode.getCS().args) !== null && _b !== void 0 ? _b : [];
828
+ argsOffset = (_c = ptNode.getArgsOffset()) !== null && _c !== void 0 ? _c : 0;
829
+ callerCid = (_d = ptNode.getOriginCid()) !== null && _d !== void 0 ? _d : callerCid;
830
+ }
831
+ srcNodes.push(...this.addCallParamPagEdge(calleeMethod, realArgs, cs.callStmt, callerCid, calleeCid, argsOffset));
832
+ srcNodes.push(...this.addCallReturnPagEdge(calleeMethod, cs.callStmt, callerCid, calleeCid));
833
+ return srcNodes;
834
+ }
835
+ /**
836
+ * only process the param PAG edge for invoke stmt
837
+ */
838
+ addCallParamPagEdge(calleeMethod, args, callStmt, callerCid, calleeCid, offset) {
839
+ var _a;
796
840
  let params = calleeMethod.getCfg().getStmts()
797
841
  .filter(stmt => stmt instanceof Stmt_1.ArkAssignStmt && stmt.getRightOp() instanceof Ref_1.ArkParameterRef)
798
842
  .map(stmt => stmt.getRightOp());
799
- srcNodes.push(...this.addCallParamPagEdge(params, cs, callerCid, calleeCid));
843
+ let srcNodes = [];
844
+ /**
845
+ * process foreach situation
846
+ * e.g. arr.forEach((item) => { ... })
847
+ * cs.args is anonymous method local, will have only 1 parameter
848
+ * but inside foreach will have >= 1 parameters
849
+ */
850
+ if (((_a = callStmt.getInvokeExpr()) === null || _a === void 0 ? void 0 : _a.getMethodSignature().getMethodSubSignature().getMethodName()) === 'forEach') {
851
+ srcNodes.push(...this.addForeachParamPagEdge(callerCid, calleeCid, callStmt, params));
852
+ return srcNodes;
853
+ }
854
+ // add args to parameters edges
855
+ for (let i = offset; i <= args.length; i++) {
856
+ let arg = args.at(i);
857
+ let param = params.at(i - offset);
858
+ if (!arg || !param) {
859
+ return srcNodes;
860
+ }
861
+ if (arg instanceof Constant_1.Constant || arg instanceof Expr_1.AbstractExpr) {
862
+ // TODO: handle AbstractExpr
863
+ continue;
864
+ }
865
+ // Get or create new PAG node for argument and parameter
866
+ let srcPagNode = this.getOrNewPagNode(callerCid, arg, callStmt);
867
+ let dstPagNode = this.getOrNewPagNode(calleeCid, param, callStmt);
868
+ this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, callStmt);
869
+ srcNodes.push(srcPagNode.getID());
870
+ // TODO: handle other types of parmeters
871
+ }
872
+ return srcNodes;
873
+ }
874
+ /**
875
+ * temporary solution for foreach
876
+ * deprecate when foreach is handled by built-in method
877
+ * connect the element node with the value inside foreach
878
+ */
879
+ addForeachParamPagEdge(callerCid, calleeCid, callStmt, params) {
880
+ // container value is the base value of callstmt, its points-to is PagNewContainerExprNode
881
+ let srcNodes = [];
882
+ let containerValue = callStmt.getInvokeExpr().getBase();
883
+ let param = params.at(0);
884
+ if (!containerValue || !param) {
885
+ return srcNodes;
886
+ }
887
+ let basePagNode = this.getOrNewPagNode(callerCid, containerValue, callStmt);
888
+ let dstPagNode = this.getOrNewPagNode(calleeCid, param, callStmt);
889
+ for (let pt of basePagNode.getPointTo()) {
890
+ let newContainerExprPagNode = this.pag.getNode(pt);
891
+ // PagNewContainerExprNode's points-to is the element node
892
+ if (!newContainerExprPagNode || !newContainerExprPagNode.getElementNode()) {
893
+ continue;
894
+ }
895
+ let srcPagNode = this.pag.getNode(newContainerExprPagNode.getElementNode());
896
+ // connect the element node with the value inside foreach
897
+ this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, callStmt);
898
+ srcNodes.push(srcPagNode.getID());
899
+ }
900
+ return srcNodes;
901
+ }
902
+ /**
903
+ * process the return value PAG edge for invoke stmt
904
+ */
905
+ addCallReturnPagEdge(calleeMethod, callStmt, callerCid, calleeCid) {
906
+ let srcNodes = [];
800
907
  // add ret to caller edges
801
908
  let retStmts = calleeMethod.getReturnStmt();
802
909
  // TODO: call statement must be a assignment state
803
- if (cs.callStmt instanceof Stmt_1.ArkAssignStmt) {
804
- let retDst = cs.callStmt.getLeftOp();
910
+ if (callStmt instanceof Stmt_1.ArkAssignStmt) {
911
+ let retDst = callStmt.getLeftOp();
805
912
  for (let retStmt of retStmts) {
806
913
  let retValue = retStmt.getOp();
807
914
  if (retValue instanceof Local_1.Local) {
808
915
  let srcPagNode = this.getOrNewPagNode(calleeCid, retValue, retStmt);
809
- let dstPagNode = this.getOrNewPagNode(callerCid, retDst, cs.callStmt);
916
+ let dstPagNode = this.getOrNewPagNode(callerCid, retDst, callStmt);
810
917
  this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, retStmt);
811
918
  }
812
919
  else if (retValue instanceof Constant_1.Constant) {
@@ -838,62 +945,6 @@ class PagBuilder {
838
945
  srcNodes.push(...this.addSDKMethodReturnPagEdge(cs, callerCid, calleeCid, calleeMethod));
839
946
  return srcNodes;
840
947
  }
841
- addCallParamPagEdge(params, cs, callerCid, calleeCid) {
842
- var _a, _b, _c;
843
- let srcNodes = [];
844
- let argNum = (_a = cs.args) === null || _a === void 0 ? void 0 : _a.length;
845
- if (argNum === params.length) {
846
- // add args to parameters edges
847
- for (let i = 0; i < argNum; i++) {
848
- let arg = (_b = cs.args) === null || _b === void 0 ? void 0 : _b.at(i);
849
- let param = params.at(i);
850
- if (!arg || !param) {
851
- return srcNodes;
852
- }
853
- if (arg instanceof Constant_1.Constant || arg instanceof Expr_1.AbstractExpr) {
854
- // TODO: handle AbstractExpr
855
- continue;
856
- }
857
- // Get or create new PAG node for argument and parameter
858
- let srcPagNode = this.getOrNewPagNode(callerCid, arg, cs.callStmt);
859
- let dstPagNode = this.getOrNewPagNode(calleeCid, param, cs.callStmt);
860
- this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
861
- srcNodes.push(srcPagNode.getID());
862
- // TODO: handle other types of parmeters
863
- }
864
- }
865
- else {
866
- /**
867
- * process foreach situation
868
- * e.g. arr.forEach((item) => { ... })
869
- * cs.args is anonymous method local, will have only 1 parameter
870
- * but inside foreach will have >= 1 parameters
871
- */
872
- if (!(((_c = cs.callStmt.getInvokeExpr()) === null || _c === void 0 ? void 0 : _c.getMethodSignature().getMethodSubSignature().getMethodName()) === 'forEach')) {
873
- return srcNodes;
874
- }
875
- // container value is the base value of callstmt, its points-to is PagNewContainerExprNode
876
- let containerValue = cs.callStmt.getInvokeExpr().getBase();
877
- let param = params.at(0);
878
- if (!containerValue || !param) {
879
- return srcNodes;
880
- }
881
- let basePagNode = this.getOrNewPagNode(callerCid, containerValue, cs.callStmt);
882
- let dstPagNode = this.getOrNewPagNode(calleeCid, param, cs.callStmt);
883
- for (let pt of basePagNode.getPointTo()) {
884
- let newContainerExprPagNode = this.pag.getNode(pt);
885
- // PagNewContainerExprNode's points-to is the element node
886
- if (!newContainerExprPagNode || !newContainerExprPagNode.getElementNode()) {
887
- continue;
888
- }
889
- let srcPagNode = this.pag.getNode(newContainerExprPagNode.getElementNode());
890
- // connect the element node with the value inside foreach
891
- this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
892
- srcNodes.push(srcPagNode.getID());
893
- }
894
- }
895
- return srcNodes;
896
- }
897
948
  addSDKMethodPagCallEdge(cs, callerCid, calleeCid) {
898
949
  let srcNodes = [];
899
950
  let calleeNode = this.cg.getNode(cs.calleeFuncID);
@@ -901,8 +952,9 @@ class PagBuilder {
901
952
  if (!calleeMethod) {
902
953
  return srcNodes;
903
954
  }
955
+ let methodType = (0, PTAUtils_1.getBuiltInApiType)(calleeMethod.getSignature());
904
956
  // block the container SDK
905
- if ((0, PTAUtils_1.IsCollectionAPI)(calleeMethod.getSignature())) {
957
+ if (methodType === PTAUtils_1.BuiltApiType.SetAdd || PTAUtils_1.BuiltApiType.MapSet) {
906
958
  return srcNodes;
907
959
  }
908
960
  if (!this.methodParamValueMap.has(calleeNode.getID())) {
@@ -941,70 +993,45 @@ class PagBuilder {
941
993
  var _a, _b;
942
994
  let argNum = (_a = cs.args) === null || _a === void 0 ? void 0 : _a.length;
943
995
  let srcNodes = [];
944
- if (argNum) {
945
- // add args to parameters edges
946
- for (let i = 0; i < argNum; i++) {
947
- let arg = (_b = cs.args) === null || _b === void 0 ? void 0 : _b.at(i);
948
- let paramValue;
949
- if (arg instanceof Local_1.Local && arg.getType() instanceof Type_1.FunctionType) {
950
- // TODO: cannot find value
951
- paramValue = this.methodParamValueMap.get(funcID).get(i);
952
- }
953
- else {
954
- continue;
955
- }
956
- if (arg && paramValue) {
957
- // Get or create new PAG node for argument and parameter
958
- let srcPagNode = this.getOrNewPagNode(callerCid, arg, cs.callStmt);
959
- let dstPagNode = this.getOrNewPagNode(calleeCid, paramValue, cs.callStmt);
960
- if (dstPagNode instanceof Pag_1.PagLocalNode) {
961
- // set the fake param Value in PagLocalNode
962
- /**
963
- * TODO: !!!
964
- * some API param is in the form of anonymous method:
965
- * component/common.d.ts
966
- * declare function animateTo(value: AnimateParam, event: () => void): void;
967
- *
968
- * this param fake Value will create PagFuncNode rather than PagLocalNode
969
- * when this API is called, the anonymous method pointer will not be able to pass into the fake Value PagNode
970
- */
971
- dstPagNode.setSdkParam();
972
- let sdkParamInvokeStmt = new Stmt_1.ArkInvokeStmt(new Expr_1.ArkPtrInvokeExpr(arg.getType().getMethodSignature(), paramValue, []));
973
- // create new DynCallSite
974
- let sdkParamCallSite = new CallGraph_1.DynCallSite(funcID, sdkParamInvokeStmt, undefined, undefined);
975
- dstPagNode.addRelatedDynCallSite(sdkParamCallSite);
976
- }
977
- this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
978
- srcNodes.push(srcPagNode.getID());
979
- }
980
- }
981
- }
982
- return srcNodes;
983
- }
984
- processContainerPagCallEdge(cs, cid, baseClassPTNode) {
985
- let srcNodes = [];
986
- let calleeNode = this.cg.getNode(cs.calleeFuncID);
987
- let calleeMethod = this.scene.getMethod(calleeNode.getMethod());
988
- let ptNode = this.pag.getNode(baseClassPTNode);
989
- if (!calleeMethod || !(ptNode instanceof Pag_1.PagNewContainerExprNode)) {
996
+ if (!argNum) {
990
997
  return srcNodes;
991
998
  }
992
- let containerValue = cs.callStmt.getInvokeExpr().getBase();
993
- const containerValueProcess = (argIndex) => {
994
- let srcNode = this.pag.getOrNewNode(cid, cs.args[argIndex], cs.callStmt);
995
- let realContainerFieldPagNode = this.pag.getOrClonePagContainerFieldNode(baseClassPTNode, undefined, containerValue);
996
- if (realContainerFieldPagNode) {
997
- // In some cases, the value of a variable of array type may not be an explicit array object,
998
- // and the value of `realContainerFieldPagNode` will be undefined.
999
- this.pag.addPagEdge(srcNode, realContainerFieldPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
1000
- srcNodes.push(srcNode.getID());
999
+ // add args to parameters edges
1000
+ for (let i = 0; i < argNum; i++) {
1001
+ let arg = (_b = cs.args) === null || _b === void 0 ? void 0 : _b.at(i);
1002
+ let paramValue;
1003
+ if (arg instanceof Local_1.Local && arg.getType() instanceof Type_1.FunctionType) {
1004
+ // TODO: cannot find value
1005
+ paramValue = this.methodParamValueMap.get(funcID).get(i);
1001
1006
  }
1002
- };
1003
- if ((0, PTAUtils_1.IsCollectionSetAdd)(calleeMethod.getSignature())) {
1004
- containerValueProcess(0);
1005
- }
1006
- else if ((0, PTAUtils_1.IsCollectionMapSet)(calleeMethod.getSignature())) {
1007
- containerValueProcess(1);
1007
+ else {
1008
+ continue;
1009
+ }
1010
+ if (!(arg && paramValue)) {
1011
+ continue;
1012
+ }
1013
+ // Get or create new PAG node for argument and parameter
1014
+ let srcPagNode = this.getOrNewPagNode(callerCid, arg, cs.callStmt);
1015
+ let dstPagNode = this.getOrNewPagNode(calleeCid, paramValue, cs.callStmt);
1016
+ if (dstPagNode instanceof Pag_1.PagLocalNode) {
1017
+ // set the fake param Value in PagLocalNode
1018
+ /**
1019
+ * TODO: !!!
1020
+ * some API param is in the form of anonymous method:
1021
+ * component/common.d.ts
1022
+ * declare function animateTo(value: AnimateParam, event: () => void): void;
1023
+ *
1024
+ * this param fake Value will create PagFuncNode rather than PagLocalNode
1025
+ * when this API is called, the anonymous method pointer will not be able to pass into the fake Value PagNode
1026
+ */
1027
+ dstPagNode.setSdkParam();
1028
+ let sdkParamInvokeStmt = new Stmt_1.ArkInvokeStmt(new Expr_1.ArkPtrInvokeExpr(arg.getType().getMethodSignature(), paramValue, []));
1029
+ // create new DynCallSite
1030
+ let sdkParamCallSite = new CallGraph_1.DynCallSite(funcID, sdkParamInvokeStmt, undefined, undefined);
1031
+ dstPagNode.addRelatedDynCallSite(sdkParamCallSite);
1032
+ }
1033
+ this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
1034
+ srcNodes.push(srcPagNode.getID());
1008
1035
  }
1009
1036
  return srcNodes;
1010
1037
  }
@@ -1257,6 +1284,129 @@ class PagBuilder {
1257
1284
  }
1258
1285
  return Pag_1.PagEdgeKind.Unknown;
1259
1286
  }
1287
+ /**
1288
+ * process Storage API
1289
+ * @returns boolean: check if the cs represent a Storage API, no matter the API will success or fail
1290
+ */
1291
+ processStorage(cs, calleeCGNode, cid) {
1292
+ let storageName = calleeCGNode.getMethod().getDeclaringClassSignature().getClassName();
1293
+ let storageType = this.getStorageType(storageName, cs, cid);
1294
+ // TODO: add other storages
1295
+ if (storageType === Pag_1.StorageType.APP_STORAGE) {
1296
+ let calleeName = calleeCGNode.getMethod().getMethodSubSignature().getMethodName();
1297
+ // TODO: complete AppStorage API
1298
+ if (calleeName === 'setOrCreate') {
1299
+ this.processStorageSetOrCreate(cs, cid);
1300
+ }
1301
+ else if (calleeName === 'link') {
1302
+ this.processStorageLink(cs, cid);
1303
+ }
1304
+ else if (calleeName === 'prop') {
1305
+ this.processStorageProp(cs, cid);
1306
+ }
1307
+ else if (calleeName === 'set') {
1308
+ this.processStorageSet(cs, cid);
1309
+ }
1310
+ else if (calleeName === 'get') {
1311
+ this.processStorageGet(cs, cid);
1312
+ }
1313
+ return true;
1314
+ }
1315
+ else if (storageType === Pag_1.StorageType.LOCAL_STORAGE) {
1316
+ // TODO: LocalStorage is not Static
1317
+ }
1318
+ return false;
1319
+ }
1320
+ processStorageSetOrCreate(cs, cid) {
1321
+ let propertyStr = this.getPropertyName(cs.args[0]);
1322
+ if (!propertyStr) {
1323
+ return;
1324
+ }
1325
+ let propertyName = propertyStr;
1326
+ let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
1327
+ let storageObj = cs.args[1];
1328
+ this.addPropertyLinkEdge(propertyNode, storageObj, cid, cs.callStmt, Pag_1.StorageLinkEdgeType.Local2Property);
1329
+ }
1330
+ processStorageLink(cs, cid) {
1331
+ let propertyStr = this.getPropertyName(cs.args[0]);
1332
+ if (!propertyStr) {
1333
+ return;
1334
+ }
1335
+ let propertyName = propertyStr;
1336
+ let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
1337
+ let leftOp = cs.callStmt.getLeftOp();
1338
+ let linkedOpNode = this.pag.getOrNewNode(cid, leftOp);
1339
+ if (linkedOpNode instanceof Pag_1.PagLocalNode) {
1340
+ linkedOpNode.setStorageLink(Pag_1.StorageType.APP_STORAGE, propertyName);
1341
+ }
1342
+ this.pag.addPagEdge(propertyNode, linkedOpNode, Pag_1.PagEdgeKind.Copy);
1343
+ this.pag.addPagEdge(linkedOpNode, propertyNode, Pag_1.PagEdgeKind.Copy);
1344
+ }
1345
+ processStorageProp(cs, cid) {
1346
+ let propertyStr = this.getPropertyName(cs.args[0]);
1347
+ if (!propertyStr) {
1348
+ return;
1349
+ }
1350
+ let propertyName = propertyStr;
1351
+ let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
1352
+ let leftOp = cs.callStmt.getLeftOp();
1353
+ let linkedOpNode = this.pag.getOrNewNode(cid, leftOp);
1354
+ if (linkedOpNode instanceof Pag_1.PagLocalNode) {
1355
+ linkedOpNode.setStorageLink(Pag_1.StorageType.APP_STORAGE, propertyName);
1356
+ }
1357
+ this.pag.addPagEdge(propertyNode, linkedOpNode, Pag_1.PagEdgeKind.Copy);
1358
+ }
1359
+ processStorageSet(cs, cid) {
1360
+ let ivkExpr = cs.callStmt.getInvokeExpr();
1361
+ if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
1362
+ let base = ivkExpr.getBase();
1363
+ let baseNode = this.pag.getOrNewNode(cid, base);
1364
+ if (baseNode.isStorageLinked()) {
1365
+ let argsNode = this.pag.getOrNewNode(cid, cs.args[0]);
1366
+ this.pag.addPagEdge(argsNode, baseNode, Pag_1.PagEdgeKind.Copy);
1367
+ }
1368
+ }
1369
+ else if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
1370
+ // TODO: process AppStorage.set()
1371
+ }
1372
+ }
1373
+ processStorageGet(cs, cid) {
1374
+ if (!(cs.callStmt instanceof Stmt_1.ArkAssignStmt)) {
1375
+ return;
1376
+ }
1377
+ let leftOp = cs.callStmt.getLeftOp();
1378
+ let ivkExpr = cs.callStmt.getInvokeExpr();
1379
+ let propertyName;
1380
+ if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
1381
+ let propertyStr = this.getPropertyName(cs.args[0]);
1382
+ if (propertyStr) {
1383
+ propertyName = propertyStr;
1384
+ }
1385
+ }
1386
+ else if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
1387
+ let baseNode = this.pag.getOrNewNode(cid, ivkExpr.getBase());
1388
+ if (baseNode.isStorageLinked()) {
1389
+ propertyName = baseNode.getStorage().PropertyName;
1390
+ }
1391
+ }
1392
+ let propertyNode = this.getPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
1393
+ if (!propertyNode) {
1394
+ return;
1395
+ }
1396
+ this.pag.addPagEdge(propertyNode, this.pag.getOrNewNode(cid, leftOp, cs.callStmt), Pag_1.PagEdgeKind.Copy, cs.callStmt);
1397
+ }
1398
+ getPropertyName(value) {
1399
+ if (value instanceof Local_1.Local) {
1400
+ let type = value.getType();
1401
+ if (type instanceof Type_1.StringType) {
1402
+ return type.getName();
1403
+ }
1404
+ }
1405
+ else if (value instanceof Constant_1.Constant) {
1406
+ return value.getValue();
1407
+ }
1408
+ return undefined;
1409
+ }
1260
1410
  /**
1261
1411
  * get storageType enum with method's Declaring ClassName
1262
1412
  *
@@ -1387,7 +1537,7 @@ class PagBuilder {
1387
1537
  */
1388
1538
  handleValueFromExternalScope(value, funcID, originValue) {
1389
1539
  if (value instanceof Local_1.Local) {
1390
- if (value.getDeclaringStmt()) {
1540
+ if (value.getDeclaringStmt() || (value.getName() === 'this')) {
1391
1541
  // not from external scope
1392
1542
  return;
1393
1543
  }
@@ -1435,7 +1585,6 @@ class PagBuilder {
1435
1585
  }
1436
1586
  getSourceValueFromExternalScope(value, funcID) {
1437
1587
  let sourceValue;
1438
- // TODO: first from default method
1439
1588
  sourceValue = this.getDefaultMethodSourceValue(value, funcID);
1440
1589
  if (!sourceValue) {
1441
1590
  sourceValue = this.getExportSourceValue(value, funcID);
@@ -1512,9 +1661,47 @@ class PagBuilder {
1512
1661
  let existingNodes = this.pag.getNodesByValue(exportLocal);
1513
1662
  existingNodes === null || existingNodes === void 0 ? void 0 : existingNodes.forEach(n => {
1514
1663
  this.pag.addPagEdge(this.pag.getNode(n), dstPagNode, e.kind);
1664
+ this.retriggerNodesList.add(n);
1515
1665
  });
1516
1666
  }
1517
1667
  return true;
1518
1668
  }
1669
+ getRetriggerNodes() {
1670
+ let retriggerNodes = Array.from(this.retriggerNodesList);
1671
+ this.retriggerNodesList.clear();
1672
+ return retriggerNodes;
1673
+ }
1674
+ addUpdatedNode(nodeID, diffPT) {
1675
+ var _a;
1676
+ let ptaConfig = PointerAnalysisConfig_1.PointerAnalysisConfig.getInstance();
1677
+ let updatedNode = (_a = this.updatedNodesThisRound.get(nodeID)) !== null && _a !== void 0 ? _a : new ptaConfig.ptsCollectionCtor();
1678
+ updatedNode.union(diffPT);
1679
+ this.updatedNodesThisRound.set(nodeID, updatedNode);
1680
+ }
1681
+ getUpdatedNodes() {
1682
+ return this.updatedNodesThisRound;
1683
+ }
1684
+ resetUpdatedNodes() {
1685
+ this.updatedNodesThisRound.clear();
1686
+ }
1687
+ transferArrayValues(method, arrayLocal) {
1688
+ if (!(arrayLocal instanceof Local_1.Local) || !(arrayLocal.getType() instanceof Type_1.ArrayType)) {
1689
+ return [];
1690
+ }
1691
+ /**
1692
+ * TODO: get array element values
1693
+ * need to resolve multi dimension array
1694
+ */
1695
+ const usedValuesInArray = arrayLocal.getUsedStmts().flatMap(stmt => {
1696
+ if (stmt instanceof Stmt_1.ArkAssignStmt) {
1697
+ const rightOp = stmt.getRightOp();
1698
+ if (rightOp instanceof Local_1.Local) {
1699
+ return rightOp;
1700
+ }
1701
+ }
1702
+ return [];
1703
+ });
1704
+ return usedValuesInArray;
1705
+ }
1519
1706
  }
1520
1707
  exports.PagBuilder = PagBuilder;