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.
- package/lib/callgraph/pointerAnalysis/PTAUtils.d.ts +9 -3
- package/lib/callgraph/pointerAnalysis/PTAUtils.d.ts.map +1 -1
- package/lib/callgraph/pointerAnalysis/PTAUtils.js +32 -18
- package/lib/callgraph/pointerAnalysis/Pag.d.ts +17 -1
- package/lib/callgraph/pointerAnalysis/Pag.d.ts.map +1 -1
- package/lib/callgraph/pointerAnalysis/Pag.js +48 -1
- package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts +48 -18
- package/lib/callgraph/pointerAnalysis/PagBuilder.d.ts.map +1 -1
- package/lib/callgraph/pointerAnalysis/PagBuilder.js +424 -257
- package/lib/core/base/Local.js +2 -2
- package/lib/core/common/IRInference.d.ts.map +1 -1
- package/lib/core/common/IRInference.js +7 -6
- package/lib/core/common/TypeInference.d.ts +1 -0
- package/lib/core/common/TypeInference.d.ts.map +1 -1
- package/lib/core/common/TypeInference.js +18 -3
- package/lib/utils/AstTreeUtils.d.ts +20 -1
- package/lib/utils/AstTreeUtils.d.ts.map +1 -1
- package/lib/utils/AstTreeUtils.js +65 -1
- package/package.json +2 -2
|
@@ -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 (
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
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
|
-
|
|
654
|
-
|
|
655
|
-
let
|
|
656
|
-
let
|
|
657
|
-
|
|
658
|
-
this.
|
|
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
|
-
|
|
661
|
-
|
|
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
|
-
|
|
664
|
-
|
|
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,
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
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
|
-
|
|
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
|
|
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 (
|
|
816
|
-
let retDst =
|
|
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,
|
|
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 (
|
|
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;
|