1 19 20 21 package soot.jimple.toolkits.annotation.nullcheck; 22 23 import soot.*; 24 import soot.jimple.*; 25 import soot.toolkits.graph.*; 26 import soot.toolkits.scalar.*; 27 import soot.util.*; 28 import java.util.*; 29 30 31 52 53 54 68 69 70 public class BranchedRefVarsAnalysis extends ForwardBranchedFlowAnalysis 71 { 72 75 76 private boolean isNotConservative = false; 79 80 private boolean isBranched = true; 82 83 private boolean careForAliases = false; 86 87 private boolean careForMethodCalls = true; 90 91 93 106 107 public final static int kBottom = 0; 109 public final static int kNull = 1; 110 public final static int kNonNull = 2; 111 public final static int kTop = 99; 112 113 114 protected FlowSet emptySet; 116 protected FlowSet fullSet; 117 118 119 protected Map unitToGenerateSet; 121 protected Map unitToPreserveSet; 122 123 124 protected Map unitToAnalyzedChecksSet; 126 protected Map unitToArrayRefChecksSet; 127 protected Map unitToInstanceFieldRefChecksSet; 128 protected Map unitToInstanceInvokeExprChecksSet; 129 protected Map unitToLengthExprChecksSet; 130 131 132 protected List refTypeLocals; 134 protected List refTypeInstFields; 135 protected List refTypeInstFieldBases; 136 protected List refTypeStaticFields; 137 protected List refTypeValues; 139 140 protected FlowSet tempFlowSet = null; 142 143 private HashMap valueToEquivValue = new HashMap(2293, 0.7f); 146 147 public EquivalentValue getEquivalentValue(Value v) 148 { 149 if (valueToEquivValue.containsKey(v)) 150 return (EquivalentValue) valueToEquivValue.get(v); 151 else { 152 EquivalentValue ev = new EquivalentValue(v); 153 valueToEquivValue.put(v, ev); 154 return ev; 155 } 156 } 158 private HashMap kRefBotttomPairs = new HashMap(2293, 0.7f); 161 private HashMap kRefNonNullPairs = new HashMap(2293, 0.7f); 162 private HashMap kRefNullPairs = new HashMap(2293, 0.7f); 163 private HashMap kRefTopPairs = new HashMap(2293, 0.7f); 164 165 public RefIntPair getKRefIntPair(EquivalentValue r, int v) 168 { 169 HashMap pairsMap = null; 170 171 if (v == kNonNull) 172 pairsMap = kRefNonNullPairs; 173 else if (v == kNull) 174 pairsMap = kRefNullPairs; 175 else if (v == kTop) 176 pairsMap = kRefTopPairs; 177 else if (v == kBottom) 178 pairsMap = kRefBotttomPairs; 179 else 180 throw new RuntimeException ("invalid constant ("+v+")"); 181 182 if (pairsMap.containsKey(r)) 183 return (RefIntPair) pairsMap.get(r); 184 else { 185 RefIntPair pair = new RefIntPair(r, v, this); 186 pairsMap.put(r, pair); 187 return pair; 188 } 189 } 191 198 199 200 private final boolean isAlwaysNull(Value r) 202 { 203 return ((r instanceof NullConstant) || 204 (r.getType() instanceof NullType)); 205 } 207 208 private final boolean isAlwaysTop(Value r) 211 { 212 if (isNotConservative) 213 return false; 214 else 215 return r instanceof InstanceFieldRef || r instanceof StaticFieldRef; 216 } 218 protected boolean isAlwaysNonNull(Value ro) { 219 if( ro instanceof NewExpr ) return true; 220 if( ro instanceof NewArrayExpr ) return true; 221 if( ro instanceof NewMultiArrayExpr ) return true; 222 if( ro instanceof ThisRef ) return true; 223 if( ro instanceof CaughtExceptionRef ) return true; 224 if( ro instanceof StringConstant ) return true; 225 return false; 226 } 227 228 229 230 private final boolean isAnalyzedRef(Value r) 233 { 234 if (isAlwaysNull(r) || isAlwaysTop(r)) 235 return false; 236 else if (r instanceof Local || 237 r instanceof InstanceFieldRef || 238 r instanceof StaticFieldRef) { 239 Type rType = r.getType(); 240 241 return (rType instanceof RefType || rType instanceof ArrayType); 242 } else 243 return false; 244 } 246 protected final int refInfo(EquivalentValue r, FlowSet fs) 250 { 251 boolean isNull = fs.contains(getKRefIntPair(r, kNull)); 252 boolean isNonNull = fs.contains(getKRefIntPair(r, kNonNull)); 253 254 if (isNull && isNonNull) 255 return kTop; 256 else if (isNull) 257 return kNull; 258 else if (isNonNull) 259 return kNonNull; 260 else 261 return kBottom; 262 } 264 protected final int refInfo(Value r, FlowSet fs) 265 { 266 return refInfo(getEquivalentValue(r), fs); 267 } 269 public int anyRefInfo(Value r, FlowSet f) 272 { 273 if (isAlwaysNull(r)) 274 return kNull; 275 else if (isAlwaysTop(r)) 276 return kTop; 277 else if( isAlwaysNonNull(r) ) 278 return kNonNull; 279 else 280 return refInfo(r, f); 281 } 283 284 299 300 private final void uAddTopToFlowSet(EquivalentValue r, FlowSet genFS, FlowSet preFS) 302 { 303 RefIntPair nullPair = getKRefIntPair(r, kNull); 304 RefIntPair nullNonPair = getKRefIntPair(r, kNonNull); 305 306 if (genFS != preFS) { 307 preFS.remove(nullPair, preFS); 308 preFS.remove(nullNonPair, preFS); 309 } 310 311 genFS.add(nullPair, genFS); 312 genFS.add(nullNonPair, genFS); 313 } 315 private final void uAddTopToFlowSet(Value r, FlowSet genFS, FlowSet preFS) 316 { 317 uAddTopToFlowSet(getEquivalentValue(r), genFS, preFS); 318 } 320 private final void uAddTopToFlowSet(Value r, FlowSet fs) 322 { 323 uAddTopToFlowSet(getEquivalentValue(r), fs, fs); 324 } 326 private final void uAddTopToFlowSet(EquivalentValue r, FlowSet fs) 328 { 329 uAddTopToFlowSet(r, fs, fs); 330 } 332 private final void uAddInfoToFlowSet(EquivalentValue r, int v, FlowSet genFS, FlowSet preFS) 334 { 335 int kill; 336 if (v == kNull) 337 kill = kNonNull; 338 else if (v == kNonNull) 339 kill = kNull; 340 else 341 throw new RuntimeException ("invalid info"); 342 343 if (genFS != preFS) { 344 preFS.remove(getKRefIntPair(r, kill), preFS); 345 } 346 347 genFS.remove(getKRefIntPair(r, kill), genFS); 348 genFS.add(getKRefIntPair(r, v), genFS); 349 } 351 private final void uAddInfoToFlowSet(Value r, int v, FlowSet genF, FlowSet preF) 352 { 353 uAddInfoToFlowSet(getEquivalentValue(r), v, genF, preF); 354 } 356 private final void uAddInfoToFlowSet(Value r, int v, FlowSet fs) 358 { 359 uAddInfoToFlowSet(getEquivalentValue(r), v, fs, fs); 360 } 362 private final void uAddInfoToFlowSet(EquivalentValue r, int v, FlowSet fs) 364 { 365 uAddInfoToFlowSet(r, v, fs, fs); 366 } 368 369 private final void uListAddTopToFlowSet(List refs, FlowSet genFS, FlowSet preFS) 371 { 372 Iterator it = refs.iterator(); 373 374 while (it.hasNext()) { 375 uAddTopToFlowSet((EquivalentValue) it.next(), genFS, preFS); 376 } 377 } 379 380 381 382 383 public BranchedRefVarsAnalysis (UnitGraph g) 386 { 387 super(g); 388 389 initRefTypeLists(); 391 392 initUniverseSets(); 394 395 initUnitSets(); 398 399 doAnalysis(); 400 } 402 403 private void initRefTypeLists() 407 { 408 refTypeLocals = new ArrayList(); 409 refTypeInstFields = new ArrayList(); 410 refTypeInstFieldBases = new ArrayList(); 411 refTypeStaticFields = new ArrayList(); 412 refTypeValues = new ArrayList(); 413 414 Iterator it = ((UnitGraph)graph).getBody().getLocals().iterator(); 416 417 while (it.hasNext()) { 418 Local l = (Local) (it.next()); 419 420 if (l.getType() instanceof RefType || 421 l.getType() instanceof ArrayType) { 422 refTypeLocals.add(getEquivalentValue(l)); 423 } 424 } 425 426 if (isNotConservative) { 427 430 Iterator unitIt = graph.iterator(); 431 432 while(unitIt.hasNext()) { 433 434 Unit s = (Unit) unitIt.next(); 435 436 Iterator boxIt; 437 boxIt = s.getUseBoxes().iterator(); 438 while(boxIt.hasNext()) initRefTypeLists( (ValueBox) boxIt.next() ); 439 boxIt = s.getDefBoxes().iterator(); 440 while(boxIt.hasNext()) initRefTypeLists( (ValueBox) boxIt.next() ); 441 442 } 443 444 } 446 refTypeValues.addAll(refTypeLocals); 447 refTypeValues.addAll(refTypeInstFields); 448 refTypeValues.addAll(refTypeStaticFields); 449 450 } 453 private void initRefTypeLists( ValueBox box ) { 454 Value val = box.getValue(); 455 Type opType = null; 456 457 if (val instanceof InstanceFieldRef) { 458 459 InstanceFieldRef ir = (InstanceFieldRef) val; 460 461 opType = ir.getType(); 462 if (opType instanceof RefType || 463 opType instanceof ArrayType) { 464 465 EquivalentValue eir = getEquivalentValue(ir); 466 467 if (!refTypeInstFields.contains(eir)) { 468 refTypeInstFields.add(eir); 469 470 EquivalentValue eirbase = getEquivalentValue(ir.getBase()); 471 if (!refTypeInstFieldBases.contains(eirbase)) 472 refTypeInstFieldBases.add(eirbase); 473 } 474 475 } 476 } else if (val instanceof StaticFieldRef) { 477 478 StaticFieldRef sr = (StaticFieldRef) val; 479 opType = sr.getType(); 480 481 if (opType instanceof RefType || 482 opType instanceof ArrayType) { 483 484 EquivalentValue esr = getEquivalentValue(sr); 485 486 if (!refTypeStaticFields.contains(esr)) { 487 refTypeStaticFields.add(esr); 488 } 489 } 490 } 491 } 492 private void initUniverseSets() 495 { 496 FlowUniverse localUniverse; 497 498 Object [] refTypeValuesArray = refTypeValues.toArray(); 499 int len = refTypeValuesArray.length; 500 Object [] universeArray = new Object [2*len]; 501 int i; 502 503 508 for (i = 0; i < len; i++) { 509 int j = i*2; 510 EquivalentValue r = (EquivalentValue) refTypeValuesArray[i]; 511 universeArray[j] = getKRefIntPair(r, kNull); 512 universeArray[j+1] = getKRefIntPair(r, kNonNull); 513 } 514 515 localUniverse = new ArrayFlowUniverse(universeArray); 516 517 emptySet = new ArrayPackedSet(localUniverse); 518 fullSet = (FlowSet) emptySet.clone(); 519 ((ArrayPackedSet) emptySet).complement(fullSet); 520 521 tempFlowSet = (FlowSet) newInitialFlow(); 522 } 524 525 526 private void initUnitSets() 527 { 528 int cap = graph.size() * 2 + 1; 529 float load = 0.7f; 530 531 unitToGenerateSet = new HashMap(cap, load); 532 unitToPreserveSet = new HashMap(cap, load); 533 534 unitToAnalyzedChecksSet = new HashMap(cap, load); 535 unitToArrayRefChecksSet = new HashMap(cap, load); 536 unitToInstanceFieldRefChecksSet = new HashMap(cap, load); 537 unitToInstanceInvokeExprChecksSet = new HashMap(cap, load); 538 unitToLengthExprChecksSet = new HashMap(cap, load); 539 540 541 Iterator unitIt = graph.iterator(); 542 543 while(unitIt.hasNext()) { 544 545 Unit s = (Unit) unitIt.next(); 546 547 FlowSet genSet = (FlowSet) emptySet.clone(); 548 FlowSet preSet = (FlowSet) fullSet.clone(); 549 550 HashSet analyzedChecksSet = new HashSet(5, load); 551 HashSet arrayRefChecksSet = new HashSet(5, load); 552 HashSet instanceFieldRefChecksSet = new HashSet(5, load); 553 HashSet instanceInvokeExprChecksSet = new HashSet(5, load); 554 HashSet lengthExprChecksSet = new HashSet(5, load); 555 556 557 559 if (careForMethodCalls && ((Stmt)s).containsInvokeExpr()) { 561 uListAddTopToFlowSet(refTypeInstFields, genSet, preSet); 562 uListAddTopToFlowSet(refTypeStaticFields, genSet, preSet); 563 } 564 565 if (careForAliases && (s instanceof AssignStmt)) { 566 AssignStmt as = (AssignStmt) s; 567 Value lhs = as.getLeftOp(); 568 569 if (refTypeInstFieldBases.contains(lhs)) { 570 575 Iterator refTypeInstFieldsIt=refTypeInstFields.iterator(); 576 577 while (refTypeInstFieldsIt.hasNext()) { 578 EquivalentValue eifr = (EquivalentValue) refTypeInstFieldsIt.next(); 579 InstanceFieldRef ifr = (InstanceFieldRef) eifr.getValue(); 580 581 if (ifr.getBase() == lhs) { 582 uAddTopToFlowSet(eifr, genSet, preSet); 583 } 584 } 585 } 586 587 if (lhs instanceof InstanceFieldRef) { 588 589 592 String lhsName = 593 ((InstanceFieldRef) lhs).getField().getName(); 594 595 Iterator refTypeInstFieldsIt = refTypeInstFields.iterator(); 596 597 while (refTypeInstFieldsIt.hasNext()) { 598 EquivalentValue eifr = (EquivalentValue) refTypeInstFieldsIt.next(); 599 InstanceFieldRef ifr = (InstanceFieldRef) eifr.getValue(); 600 601 String name = ifr.getField().getName(); 602 603 if (name.equals(lhsName)) { 604 uAddTopToFlowSet(eifr, genSet, preSet); 605 } 606 } 607 } 608 } 610 { 612 Iterator boxIt = s.getDefBoxes().iterator(); 613 614 while(boxIt.hasNext()) { 615 616 ValueBox box = (ValueBox) boxIt.next(); 617 Value boxValue = box.getValue(); 618 619 if (isAnalyzedRef(boxValue)) { 620 uAddTopToFlowSet(boxValue, genSet, preSet); 621 } 622 } 623 } 625 627 if (s instanceof DefinitionStmt) { 628 DefinitionStmt as = (DefinitionStmt) s; 629 Value ro = as.getRightOp(); 630 Value lo = as.getLeftOp(); 631 632 if (ro instanceof CastExpr) 634 ro = ((CastExpr) ro).getOp(); 635 636 if (isAnalyzedRef(lo)) { 637 if (isAlwaysNonNull(ro)) { 638 uAddInfoToFlowSet(lo, kNonNull, genSet, preSet); 639 } else if (isAlwaysNull(ro)) { 640 uAddInfoToFlowSet(lo, kNull, genSet, preSet); 641 } else if (isAlwaysTop(ro)) { 642 uAddTopToFlowSet(lo, genSet, preSet); 643 } 644 } 645 } 647 { 651 Iterator boxIt; 652 boxIt = s.getUseBoxes().iterator(); 653 while(boxIt.hasNext()) { 654 Value boxValue = ((ValueBox) boxIt.next()).getValue(); 655 Value base = null; 656 657 if(boxValue instanceof InstanceFieldRef) { 658 base = ((InstanceFieldRef) (boxValue)).getBase(); 659 instanceFieldRefChecksSet.add(base); 660 } else if (boxValue instanceof ArrayRef) { 661 base = ((ArrayRef) (boxValue)).getBase(); 662 arrayRefChecksSet.add(base); 663 } else if (boxValue instanceof InstanceInvokeExpr) { 664 base = ((InstanceInvokeExpr) boxValue).getBase(); 665 instanceInvokeExprChecksSet.add(base); 666 } else if (boxValue instanceof LengthExpr) { 667 base = ((LengthExpr) boxValue).getOp(); 668 lengthExprChecksSet.add(base); 669 } else if (s instanceof ThrowStmt) { 670 base = ((ThrowStmt)s).getOp(); 671 } else if (s instanceof MonitorStmt) { 672 base = ((MonitorStmt)s).getOp(); 673 } 674 675 if (base != null && isAnalyzedRef(base)) { 676 uAddInfoToFlowSet(base, kNonNull, genSet, preSet); 677 analyzedChecksSet.add(base); 678 } 679 } 680 boxIt = s.getDefBoxes().iterator(); 681 while(boxIt.hasNext()) { 682 683 Value boxValue = ((ValueBox) boxIt.next()).getValue(); 684 Value base = null; 685 686 if(boxValue instanceof InstanceFieldRef) { 687 base = ((InstanceFieldRef) (boxValue)).getBase(); 688 instanceFieldRefChecksSet.add(base); 689 } else if (boxValue instanceof ArrayRef) { 690 base = ((ArrayRef) (boxValue)).getBase(); 691 arrayRefChecksSet.add(base); 692 } else if (boxValue instanceof InstanceInvokeExpr) { 693 base = ((InstanceInvokeExpr) boxValue).getBase(); 694 instanceInvokeExprChecksSet.add(base); 695 } else if (boxValue instanceof LengthExpr) { 696 base = ((LengthExpr) boxValue).getOp(); 697 lengthExprChecksSet.add(base); 698 } else if (s instanceof ThrowStmt) { 699 base = ((ThrowStmt)s).getOp(); 700 } else if (s instanceof MonitorStmt) { 701 base = ((MonitorStmt)s).getOp(); 702 } 703 704 if (base != null && isAnalyzedRef(base)) { 705 uAddInfoToFlowSet(base, kNonNull, genSet, preSet); 706 analyzedChecksSet.add(base); 707 } 708 } 709 } 711 unitToGenerateSet.put(s, genSet); 712 unitToPreserveSet.put(s, preSet); 713 714 unitToAnalyzedChecksSet.put(s, analyzedChecksSet); 715 unitToArrayRefChecksSet.put(s, arrayRefChecksSet); 716 unitToInstanceFieldRefChecksSet.put(s, instanceFieldRefChecksSet); 717 unitToInstanceInvokeExprChecksSet.put(s, instanceInvokeExprChecksSet); 718 unitToLengthExprChecksSet.put(s, lengthExprChecksSet); 719 } 720 } 722 protected void flowThrough(Object inValue, Unit stmt, List outFallValue, List outBranchValues) 723 { 724 FlowSet in = (FlowSet) inValue; 725 FlowSet out = tempFlowSet; 726 FlowSet pre = (FlowSet) unitToPreserveSet.get(stmt); 727 FlowSet gen = (FlowSet) unitToGenerateSet.get(stmt); 728 729 in.intersection(pre, out); 731 732 out.union(gen, out); 734 735 if (stmt instanceof AssignStmt) { 738 AssignStmt as = (AssignStmt) stmt; 739 Value rightOp = as.getRightOp(); 740 Value leftOp = as.getLeftOp(); 741 742 if (rightOp instanceof CastExpr) 744 rightOp = ((CastExpr) rightOp).getOp(); 745 746 if (isAnalyzedRef(leftOp) && isAnalyzedRef(rightOp)) { 747 int roInfo = refInfo(rightOp, in); 748 749 if (roInfo == kTop) 750 uAddTopToFlowSet(leftOp, out); 751 else if (roInfo != kBottom) 752 uAddInfoToFlowSet(leftOp, roInfo, out); 753 } 754 } 755 756 { 758 Iterator it = outBranchValues.iterator(); 759 while (it.hasNext()) { 760 FlowSet fs = (FlowSet) (it.next()); 761 762 copy(out, fs); 763 } 764 } 765 766 { 768 Iterator it = outFallValue.iterator(); 769 while (it.hasNext()) { 770 FlowSet fs = (FlowSet) (it.next()); 771 772 copy(out, fs); 773 } 774 } 775 776 if (isBranched && (stmt instanceof IfStmt)) { 777 Value cond = ((IfStmt) stmt).getCondition(); 778 Value op1 = ((BinopExpr) cond).getOp1(); 779 Value op2 = ((BinopExpr) cond).getOp2(); 780 781 if ((!(isAlwaysTop(op1) || isAlwaysTop(op2))) && (isAnalyzedRef(op1) || isAnalyzedRef(op2))) { 784 Value toGen = null; 785 int toGenInfo = kBottom; 786 787 int op1Info = anyRefInfo(op1, in); 788 int op2Info = anyRefInfo(op2, in); 789 boolean op1isKnown = (op1Info == kNull || op1Info == kNonNull); 790 boolean op2isKnown = (op2Info == kNull || op2Info == kNonNull); 791 792 if (op1isKnown) { 793 if (!op2isKnown) { 794 toGen = op2; 795 toGenInfo = op1Info; 796 } 797 } else if (op2isKnown) { 798 toGen = op1; 799 toGenInfo = op2Info; 800 } 801 802 if ((toGen != null) && isAnalyzedRef(toGen)) { 804 int fInfo = kBottom; 805 int bInfo = kBottom; 806 807 if (cond instanceof EqExpr) { 808 bInfo = toGenInfo; 810 if (toGenInfo == kNull) { 811 fInfo = kNonNull; 813 } 814 815 } else if (cond instanceof NeExpr) { 816 fInfo = toGenInfo; 818 if (toGenInfo == kNull) { 819 bInfo = kNonNull; 821 } 822 } else 823 throw new RuntimeException ("invalid condition"); 824 825 if (fInfo != kBottom) { 826 Iterator it = outFallValue.iterator(); 827 828 while(it.hasNext()) { 829 FlowSet fs = (FlowSet) (it.next()); 830 831 copy(out, fs); 832 uAddInfoToFlowSet(toGen, fInfo, fs); 833 } 834 } 835 836 if (bInfo != kBottom) { 837 Iterator it = outBranchValues.iterator(); 838 839 while (it.hasNext()) { 840 FlowSet fs = (FlowSet) (it.next()); 841 842 copy(out, fs); 843 uAddInfoToFlowSet(toGen, bInfo, fs); 844 } 845 } 846 } 847 } 848 } 849 } 851 852 protected void merge(Object in1, Object in2, Object out) 853 { 854 FlowSet inSet1 = (FlowSet) in1; 855 FlowSet inSet2 = (FlowSet) in2; 856 FlowSet inSet1Copy = (FlowSet) inSet1.clone(); 857 FlowSet inSet2Copy = (FlowSet) inSet2.clone(); 858 860 FlowSet outSet = (FlowSet) out; 861 862 inSet1.intersection(inSet2, outSet); 863 Iterator it = refTypeValues.iterator(); 866 while (it.hasNext()) { 867 EquivalentValue r = (EquivalentValue) it.next(); 868 int refInfoIn1 = refInfo(r, inSet1Copy); 869 int refInfoIn2 = refInfo(r, inSet2Copy); 870 if (refInfoIn1 != refInfoIn2) { 871 if ((refInfoIn1 == kTop) || (refInfoIn2 == kTop)) { 873 uAddTopToFlowSet(r, outSet); 875 } else if (refInfoIn1 == kBottom) { 876 uAddInfoToFlowSet(r, refInfoIn2, outSet); 878 } else if (refInfoIn2 == kBottom) { 879 uAddInfoToFlowSet(r, refInfoIn1, outSet); 881 } else { 882 uAddTopToFlowSet(r, outSet); 884 } 885 } 886 } 887 } 889 890 protected void copy(Object source, Object dest) 891 { 892 FlowSet sourceSet = (FlowSet) source, 893 destSet = (FlowSet) dest; 894 895 sourceSet.copy(destSet); 896 } 898 899 protected Object newInitialFlow() 900 { 901 return emptySet.clone(); 902 } 904 905 protected Object entryInitialFlow() 906 { 907 return fullSet.clone(); 908 } 909 910 public boolean treatTrapHandlersAsEntries() 914 { 915 return true; 916 } 917 918 } 920 | Popular Tags |