arkanalyzer 1.0.30 → 1.0.32

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.
@@ -316,7 +316,7 @@ class PagBuilder {
316
316
  this.addEdgesFromInterFuncPag(interFuncPag, cid);
317
317
  }
318
318
  this.addCallsEdgesFromFuncPag(funcPag, cid);
319
- this.addDynamicCallSite(funcPag, funcID);
319
+ this.addDynamicCallSite(funcPag, funcID, cid);
320
320
  this.addUnknownCallSite(funcPag, funcID);
321
321
  this.handledFunc.add(`${cid}-${funcID}`);
322
322
  }
@@ -371,7 +371,7 @@ class PagBuilder {
371
371
  if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
372
372
  let baseNode = this.getOrNewPagNode(cid, ivkExpr.getBase());
373
373
  let baseNodeID = baseNode.getID();
374
- this.addThisRefCallEdge(baseNodeID, cid, ivkExpr, callee, calleeCid, cs.callerFuncID);
374
+ this.addThisRefCallEdge(baseNodeID, cid, ivkExpr.getBase(), callee, calleeCid, cs.callerFuncID);
375
375
  }
376
376
  else {
377
377
  logger.error(`constructor or intrinsic func is static ${ivkExpr.toString()}`);
@@ -380,130 +380,7 @@ class PagBuilder {
380
380
  }
381
381
  return true;
382
382
  }
383
- /**
384
- * process Storage API
385
- * @returns boolean: check if the cs represent a Storage API, no matter the API will success or fail
386
- */
387
- processStorage(cs, calleeCGNode, cid) {
388
- let storageName = calleeCGNode.getMethod().getDeclaringClassSignature().getClassName();
389
- let storageType = this.getStorageType(storageName, cs, cid);
390
- // TODO: add other storages
391
- if (storageType === Pag_1.StorageType.APP_STORAGE) {
392
- let calleeName = calleeCGNode.getMethod().getMethodSubSignature().getMethodName();
393
- // TODO: complete AppStorage API
394
- if (calleeName === 'setOrCreate') {
395
- this.processStorageSetOrCreate(cs, cid);
396
- }
397
- else if (calleeName === 'link') {
398
- this.processStorageLink(cs, cid);
399
- }
400
- else if (calleeName === 'prop') {
401
- this.processStorageProp(cs, cid);
402
- }
403
- else if (calleeName === 'set') {
404
- this.processStorageSet(cs, cid);
405
- }
406
- else if (calleeName === 'get') {
407
- this.processStorageGet(cs, cid);
408
- }
409
- return true;
410
- }
411
- else if (storageType === Pag_1.StorageType.LOCAL_STORAGE) {
412
- // TODO: LocalStorage is not Static
413
- }
414
- return false;
415
- }
416
- processStorageSetOrCreate(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 storageObj = cs.args[1];
424
- this.addPropertyLinkEdge(propertyNode, storageObj, cid, cs.callStmt, Pag_1.StorageLinkEdgeType.Local2Property);
425
- }
426
- processStorageLink(cs, cid) {
427
- let propertyStr = this.getPropertyName(cs.args[0]);
428
- if (!propertyStr) {
429
- return;
430
- }
431
- let propertyName = propertyStr;
432
- let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
433
- let leftOp = cs.callStmt.getLeftOp();
434
- let linkedOpNode = this.pag.getOrNewNode(cid, leftOp);
435
- if (linkedOpNode instanceof Pag_1.PagLocalNode) {
436
- linkedOpNode.setStorageLink(Pag_1.StorageType.APP_STORAGE, propertyName);
437
- }
438
- this.pag.addPagEdge(propertyNode, linkedOpNode, Pag_1.PagEdgeKind.Copy);
439
- this.pag.addPagEdge(linkedOpNode, propertyNode, Pag_1.PagEdgeKind.Copy);
440
- }
441
- processStorageProp(cs, cid) {
442
- let propertyStr = this.getPropertyName(cs.args[0]);
443
- if (!propertyStr) {
444
- return;
445
- }
446
- let propertyName = propertyStr;
447
- let propertyNode = this.getOrNewPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
448
- let leftOp = cs.callStmt.getLeftOp();
449
- let linkedOpNode = this.pag.getOrNewNode(cid, leftOp);
450
- if (linkedOpNode instanceof Pag_1.PagLocalNode) {
451
- linkedOpNode.setStorageLink(Pag_1.StorageType.APP_STORAGE, propertyName);
452
- }
453
- this.pag.addPagEdge(propertyNode, linkedOpNode, Pag_1.PagEdgeKind.Copy);
454
- }
455
- processStorageSet(cs, cid) {
456
- let ivkExpr = cs.callStmt.getInvokeExpr();
457
- if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
458
- let base = ivkExpr.getBase();
459
- let baseNode = this.pag.getOrNewNode(cid, base);
460
- if (baseNode.isStorageLinked()) {
461
- let argsNode = this.pag.getOrNewNode(cid, cs.args[0]);
462
- this.pag.addPagEdge(argsNode, baseNode, Pag_1.PagEdgeKind.Copy);
463
- }
464
- }
465
- else if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
466
- // TODO: process AppStorage.set()
467
- }
468
- }
469
- processStorageGet(cs, cid) {
470
- if (!(cs.callStmt instanceof Stmt_1.ArkAssignStmt)) {
471
- return;
472
- }
473
- let leftOp = cs.callStmt.getLeftOp();
474
- let ivkExpr = cs.callStmt.getInvokeExpr();
475
- let propertyName;
476
- if (ivkExpr instanceof Expr_1.ArkStaticInvokeExpr) {
477
- let propertyStr = this.getPropertyName(cs.args[0]);
478
- if (propertyStr) {
479
- propertyName = propertyStr;
480
- }
481
- }
482
- else if (ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
483
- let baseNode = this.pag.getOrNewNode(cid, ivkExpr.getBase());
484
- if (baseNode.isStorageLinked()) {
485
- propertyName = baseNode.getStorage().PropertyName;
486
- }
487
- }
488
- let propertyNode = this.getPropertyNode(Pag_1.StorageType.APP_STORAGE, propertyName, cs.callStmt);
489
- if (!propertyNode) {
490
- return;
491
- }
492
- this.pag.addPagEdge(propertyNode, this.pag.getOrNewNode(cid, leftOp, cs.callStmt), Pag_1.PagEdgeKind.Copy, cs.callStmt);
493
- }
494
- getPropertyName(value) {
495
- if (value instanceof Local_1.Local) {
496
- let type = value.getType();
497
- if (type instanceof Type_1.StringType) {
498
- return type.getName();
499
- }
500
- }
501
- else if (value instanceof Constant_1.Constant) {
502
- return value.getValue();
503
- }
504
- return undefined;
505
- }
506
- addDynamicCallSite(funcPag, funcID) {
383
+ addDynamicCallSite(funcPag, funcID, cid) {
507
384
  // add dyn callsite in funcpag to base node
508
385
  for (let cs of funcPag.getDynamicCallSites()) {
509
386
  let invokeExpr = cs.callStmt.getInvokeExpr();
@@ -534,6 +411,9 @@ class PagBuilder {
534
411
  }
535
412
  node.addRelatedDynCallSite(cs);
536
413
  }
414
+ if (cs.callStmt instanceof Stmt_1.ArkAssignStmt) {
415
+ this.getOrNewPagNode(cid, cs.callStmt.getLeftOp(), cs.callStmt);
416
+ }
537
417
  }
538
418
  }
539
419
  addUnknownCallSite(funcPag, funcID) {
@@ -583,24 +463,29 @@ class PagBuilder {
583
463
  // update call graph
584
464
  // TODO: movo to cgbuilder
585
465
  this.cg.addDynamicCallEdge(callerNode.getID(), dstCGNode.getID(), cs.callStmt);
586
- if (!this.cg.detectReachable(dstCGNode.getID(), callerNode.getID())) {
587
- let calleeCid = this.ctx.getOrNewContext(cid, dstCGNode.getID(), true);
588
- let staticCS = new CallGraph_1.CallSite(cs.callStmt, cs.args, dstCGNode.getID(), cs.callerFuncID);
589
- if (this.scale === PointerAnalysisConfig_1.PtaAnalysisScale.MethodLevel) {
590
- srcNodes.push(...this.addStaticPagCallReturnEdge(staticCS, baseClassPTNode, calleeCid));
591
- continue;
592
- }
593
- srcNodes.push(...this.processContainerPagCallEdge(staticCS, cid, baseClassPTNode));
594
- srcNodes.push(...this.addStaticPagCallEdge(staticCS, cid, calleeCid));
595
- // Pass base's pts to callee's this pointer
596
- if (!dstCGNode.isSdkMethod() && ivkExpr instanceof Expr_1.ArkInstanceInvokeExpr) {
597
- let srcBaseNode = this.addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, cs.callerFuncID);
598
- srcNodes.push(srcBaseNode);
599
- }
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));
600
481
  }
601
482
  }
602
483
  return srcNodes;
603
484
  }
485
+ /**
486
+ * all possible callee methods of a dynamic call site
487
+ * handle both PtrInvokeExpr and InstanceInvokeExpr
488
+ */
604
489
  getDynamicCallee(ptNode, value, ivkExpr, cs) {
605
490
  let callee = [];
606
491
  if (ptNode instanceof Pag_1.PagFuncNode) {
@@ -650,18 +535,143 @@ class PagBuilder {
650
535
  }
651
536
  return callee;
652
537
  }
653
- addUpdatedNode(nodeID, diffPT) {
654
- var _a;
655
- let ptaConfig = PointerAnalysisConfig_1.PointerAnalysisConfig.getInstance();
656
- let updatedNode = (_a = this.updatedNodesThisRound.get(nodeID)) !== null && _a !== void 0 ? _a : new ptaConfig.ptsCollectionCtor();
657
- updatedNode.union(diffPT);
658
- this.updatedNodesThisRound.set(nodeID, updatedNode);
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;
555
+ }
556
+ this.addThisRefCallEdge(baseClassPTNode, ptNode.getOriginCid(), thisValue, callee, calleeCid, staticCS.callerFuncID);
557
+ }
558
+ return srcNodes;
659
559
  }
660
- getUpdatedNodes() {
661
- return this.updatedNodesThisRound;
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;
662
604
  }
663
- resetUpdatedNodes() {
664
- this.updatedNodesThisRound.clear();
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());
622
+ }
623
+ };
624
+ if (type === PTAUtils_1.BuiltApiType.SetAdd) {
625
+ containerValueProcess(0);
626
+ }
627
+ else if (type === PTAUtils_1.BuiltApiType.MapSet) {
628
+ containerValueProcess(1);
629
+ }
630
+ return srcNodes;
631
+ }
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);
636
+ }
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);
646
+ }
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
+ }
665
675
  }
666
676
  handleUnkownDynamicCall(cs, cid) {
667
677
  var _a;
@@ -744,22 +754,10 @@ class PagBuilder {
744
754
  }
745
755
  return reAnalyzeNodes;
746
756
  }
747
- addThisRefCallEdge(baseClassPTNode, cid, ivkExpr, callee, calleeCid, callerFunID) {
748
- var _a;
749
- if (!callee || !callee.getCfg()) {
750
- logger.error(`callee is null`);
751
- return -1;
752
- }
753
- 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);
754
- let thisPtr = (thisAssignStmt === null || thisAssignStmt === void 0 ? void 0 : thisAssignStmt.at(0)).getRightOp();
755
- if (!thisPtr) {
756
- throw new Error('Can not get this ptr');
757
- }
758
- // IMPORTANT: set cid 2 base Pt info firstly
759
- this.cid2ThisRefPtMap.set(calleeCid, baseClassPTNode);
760
- let thisRefNode = this.getOrNewThisRefNode(calleeCid, thisPtr);
761
- thisRefNode.addPTNode(baseClassPTNode);
762
- 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;
763
761
  srcBaseLocal = this.getRealThisLocal(srcBaseLocal, callerFunID);
764
762
  let srcNodeId = this.pag.hasCtxNode(cid, srcBaseLocal);
765
763
  if (!srcNodeId) {
@@ -776,12 +774,30 @@ class PagBuilder {
776
774
  this.pag.addPagEdge(this.pag.getNode(srcNodeId), thisRefNode, Pag_1.PagEdgeKind.This);
777
775
  return srcNodeId;
778
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
+ }
779
794
  /*
780
795
  * Add copy edges from arguments to parameters
781
796
  * ret edges from return values to callsite
782
797
  * Return src node
783
798
  */
784
- addStaticPagCallEdge(cs, callerCid, calleeCid) {
799
+ addStaticPagCallEdge(cs, callerCid, calleeCid, ptNode) {
800
+ var _a, _b, _c, _d;
785
801
  if (!calleeCid) {
786
802
  calleeCid = this.ctx.getOrNewContext(callerCid, cs.calleeFuncID, true);
787
803
  }
@@ -804,21 +820,100 @@ class PagBuilder {
804
820
  let calleeCS = this.buildFuncPagAndAddToWorklist(new CSFuncID(calleeCid, cs.calleeFuncID));
805
821
  // callee cid will updated if callee is singleton
806
822
  calleeCid = calleeCS.cid;
807
- // 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;
808
840
  let params = calleeMethod.getCfg().getStmts()
809
841
  .filter(stmt => stmt instanceof Stmt_1.ArkAssignStmt && stmt.getRightOp() instanceof Ref_1.ArkParameterRef)
810
842
  .map(stmt => stmt.getRightOp());
811
- 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 = [];
812
907
  // add ret to caller edges
813
908
  let retStmts = calleeMethod.getReturnStmt();
814
909
  // TODO: call statement must be a assignment state
815
- if (cs.callStmt instanceof Stmt_1.ArkAssignStmt) {
816
- let retDst = cs.callStmt.getLeftOp();
910
+ if (callStmt instanceof Stmt_1.ArkAssignStmt) {
911
+ let retDst = callStmt.getLeftOp();
817
912
  for (let retStmt of retStmts) {
818
913
  let retValue = retStmt.getOp();
819
914
  if (retValue instanceof Local_1.Local) {
820
915
  let srcPagNode = this.getOrNewPagNode(calleeCid, retValue, retStmt);
821
- let dstPagNode = this.getOrNewPagNode(callerCid, retDst, cs.callStmt);
916
+ let dstPagNode = this.getOrNewPagNode(callerCid, retDst, callStmt);
822
917
  this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, retStmt);
823
918
  }
824
919
  else if (retValue instanceof Constant_1.Constant) {
@@ -850,62 +945,6 @@ class PagBuilder {
850
945
  srcNodes.push(...this.addSDKMethodReturnPagEdge(cs, callerCid, calleeCid, calleeMethod));
851
946
  return srcNodes;
852
947
  }
853
- addCallParamPagEdge(params, cs, callerCid, calleeCid) {
854
- var _a, _b, _c;
855
- let srcNodes = [];
856
- let argNum = (_a = cs.args) === null || _a === void 0 ? void 0 : _a.length;
857
- if (argNum === params.length) {
858
- // add args to parameters edges
859
- for (let i = 0; i < argNum; i++) {
860
- let arg = (_b = cs.args) === null || _b === void 0 ? void 0 : _b.at(i);
861
- let param = params.at(i);
862
- if (!arg || !param) {
863
- return srcNodes;
864
- }
865
- if (arg instanceof Constant_1.Constant || arg instanceof Expr_1.AbstractExpr) {
866
- // TODO: handle AbstractExpr
867
- continue;
868
- }
869
- // Get or create new PAG node for argument and parameter
870
- let srcPagNode = this.getOrNewPagNode(callerCid, arg, cs.callStmt);
871
- let dstPagNode = this.getOrNewPagNode(calleeCid, param, cs.callStmt);
872
- this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
873
- srcNodes.push(srcPagNode.getID());
874
- // TODO: handle other types of parmeters
875
- }
876
- }
877
- else {
878
- /**
879
- * process foreach situation
880
- * e.g. arr.forEach((item) => { ... })
881
- * cs.args is anonymous method local, will have only 1 parameter
882
- * but inside foreach will have >= 1 parameters
883
- */
884
- if (!(((_c = cs.callStmt.getInvokeExpr()) === null || _c === void 0 ? void 0 : _c.getMethodSignature().getMethodSubSignature().getMethodName()) === 'forEach')) {
885
- return srcNodes;
886
- }
887
- // container value is the base value of callstmt, its points-to is PagNewContainerExprNode
888
- let containerValue = cs.callStmt.getInvokeExpr().getBase();
889
- let param = params.at(0);
890
- if (!containerValue || !param) {
891
- return srcNodes;
892
- }
893
- let basePagNode = this.getOrNewPagNode(callerCid, containerValue, cs.callStmt);
894
- let dstPagNode = this.getOrNewPagNode(calleeCid, param, cs.callStmt);
895
- for (let pt of basePagNode.getPointTo()) {
896
- let newContainerExprPagNode = this.pag.getNode(pt);
897
- // PagNewContainerExprNode's points-to is the element node
898
- if (!newContainerExprPagNode || !newContainerExprPagNode.getElementNode()) {
899
- continue;
900
- }
901
- let srcPagNode = this.pag.getNode(newContainerExprPagNode.getElementNode());
902
- // connect the element node with the value inside foreach
903
- this.pag.addPagEdge(srcPagNode, dstPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
904
- srcNodes.push(srcPagNode.getID());
905
- }
906
- }
907
- return srcNodes;
908
- }
909
948
  addSDKMethodPagCallEdge(cs, callerCid, calleeCid) {
910
949
  let srcNodes = [];
911
950
  let calleeNode = this.cg.getNode(cs.calleeFuncID);
@@ -913,8 +952,9 @@ class PagBuilder {
913
952
  if (!calleeMethod) {
914
953
  return srcNodes;
915
954
  }
955
+ let methodType = (0, PTAUtils_1.getBuiltInApiType)(calleeMethod.getSignature());
916
956
  // block the container SDK
917
- if ((0, PTAUtils_1.IsCollectionAPI)(calleeMethod.getSignature())) {
957
+ if (methodType === PTAUtils_1.BuiltApiType.SetAdd || PTAUtils_1.BuiltApiType.MapSet) {
918
958
  return srcNodes;
919
959
  }
920
960
  if (!this.methodParamValueMap.has(calleeNode.getID())) {
@@ -995,33 +1035,6 @@ class PagBuilder {
995
1035
  }
996
1036
  return srcNodes;
997
1037
  }
998
- processContainerPagCallEdge(cs, cid, baseClassPTNode) {
999
- let srcNodes = [];
1000
- let calleeNode = this.cg.getNode(cs.calleeFuncID);
1001
- let calleeMethod = this.scene.getMethod(calleeNode.getMethod());
1002
- let ptNode = this.pag.getNode(baseClassPTNode);
1003
- if (!calleeMethod || !(ptNode instanceof Pag_1.PagNewContainerExprNode)) {
1004
- return srcNodes;
1005
- }
1006
- let containerValue = cs.callStmt.getInvokeExpr().getBase();
1007
- const containerValueProcess = (argIndex) => {
1008
- let srcNode = this.pag.getOrNewNode(cid, cs.args[argIndex], cs.callStmt);
1009
- let realContainerFieldPagNode = this.pag.getOrClonePagContainerFieldNode(baseClassPTNode, undefined, containerValue);
1010
- if (realContainerFieldPagNode) {
1011
- // In some cases, the value of a variable of array type may not be an explicit array object,
1012
- // and the value of `realContainerFieldPagNode` will be undefined.
1013
- this.pag.addPagEdge(srcNode, realContainerFieldPagNode, Pag_1.PagEdgeKind.Copy, cs.callStmt);
1014
- srcNodes.push(srcNode.getID());
1015
- }
1016
- };
1017
- if ((0, PTAUtils_1.IsCollectionSetAdd)(calleeMethod.getSignature())) {
1018
- containerValueProcess(0);
1019
- }
1020
- else if ((0, PTAUtils_1.IsCollectionMapSet)(calleeMethod.getSignature())) {
1021
- containerValueProcess(1);
1022
- }
1023
- return srcNodes;
1024
- }
1025
1038
  getOrNewPagNode(cid, v, s) {
1026
1039
  if (v instanceof Ref_1.ArkThisRef) {
1027
1040
  return this.getOrNewThisRefNode(cid, v);
@@ -1271,6 +1284,129 @@ class PagBuilder {
1271
1284
  }
1272
1285
  return Pag_1.PagEdgeKind.Unknown;
1273
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
+ }
1274
1410
  /**
1275
1411
  * get storageType enum with method's Declaring ClassName
1276
1412
  *
@@ -1449,7 +1585,6 @@ class PagBuilder {
1449
1585
  }
1450
1586
  getSourceValueFromExternalScope(value, funcID) {
1451
1587
  let sourceValue;
1452
- // TODO: first from default method
1453
1588
  sourceValue = this.getDefaultMethodSourceValue(value, funcID);
1454
1589
  if (!sourceValue) {
1455
1590
  sourceValue = this.getExportSourceValue(value, funcID);
@@ -1536,5 +1671,37 @@ class PagBuilder {
1536
1671
  this.retriggerNodesList.clear();
1537
1672
  return retriggerNodes;
1538
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
+ }
1539
1706
  }
1540
1707
  exports.PagBuilder = PagBuilder;