00001 package edu.ksu.cis.bandera.bofa;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 import ca.mcgill.sable.soot.SootClass;
00038 import ca.mcgill.sable.soot.SootMethod;
00039 import ca.mcgill.sable.soot.jimple.AbstractJimpleValueSwitch;
00040 import ca.mcgill.sable.soot.jimple.ArrayRef;
00041 import ca.mcgill.sable.soot.jimple.InstanceFieldRef;
00042 import ca.mcgill.sable.soot.jimple.Local;
00043 import ca.mcgill.sable.soot.jimple.NonStaticInvokeExpr;
00044 import ca.mcgill.sable.soot.jimple.ParameterRef;
00045 import ca.mcgill.sable.soot.jimple.SpecialInvokeExpr;
00046 import ca.mcgill.sable.soot.jimple.StaticFieldRef;
00047 import ca.mcgill.sable.soot.jimple.Stmt;
00048 import ca.mcgill.sable.soot.jimple.ThisRef;
00049 import ca.mcgill.sable.soot.jimple.Value;
00050 import ca.mcgill.sable.util.ArrayList;
00051 import ca.mcgill.sable.util.Collection;
00052 import ca.mcgill.sable.util.Comparator;
00053 import ca.mcgill.sable.util.HashSet;
00054 import ca.mcgill.sable.util.Iterator;
00055 import ca.mcgill.sable.util.LinkedList;
00056 import ca.mcgill.sable.util.Set;
00057 import edu.ksu.cis.bandera.annotation.Annotation;
00058 import edu.ksu.cis.bandera.annotation.AnnotationManager;
00059 import edu.ksu.cis.bandera.annotation.ConstructorDeclarationAnnotation;
00060 import edu.ksu.cis.bandera.annotation.MethodDeclarationAnnotation;
00061 import edu.ksu.cis.bandera.jjjc.CompilationManager;
00062 import java.sql.Ref;
00063 import org.apache.log4j.Category;
00064 import ca.mcgill.sable.soot.NullType;
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 public class Analysis {
00086
00087
00088
00089
00090 private static Analysis singleton;
00091
00092
00093
00094
00095
00096 private static Category cat;
00097
00098
00099
00100
00101
00102 private final static int DEFS = 1;
00103
00104
00105
00106
00107
00108 private final static int USES = 2;
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 class RefValueSwitch extends AbstractJimpleValueSwitch
00124 {
00125
00126
00127
00128
00129
00130 Collection result;
00131
00132
00133
00134
00135
00136 MethodVariant method;
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 Set build(Value v, SootMethod sm)
00149 {
00150 method = MethodVariantManager.select(sm);
00151 v.apply(this);
00152 return collect();
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 private Set collect()
00169 {
00170 HashSet temp;
00171 temp = new HashSet();
00172 for (Iterator i = result.iterator(); i.hasNext();) {
00173 ValueVariant v = (ValueVariant)i.next();
00174 temp.add(new
00175 ExprStmtMethodTriple(v.getExpr(),
00176 getStmtMethodPair(v.getStmt())));
00177 }
00178 return temp;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 public void caseArrayRef(ArrayRef v)
00188 {
00189 result = method.getASTValues(v);
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199 public void caseInstanceFieldRef(InstanceFieldRef v)
00200 {
00201 Collection temp = InstanceVariantManager.getVariants(v.getField());
00202 result = new HashSet();
00203 for (Iterator i = temp.iterator(); i.hasNext();) {
00204 result.addAll(((InstanceVariant)i.next()).getNode()
00205 .getValues());
00206 }
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 public void caseParameterRef(ParameterRef v)
00216 {
00217 result = method.getParameterValues(v.getIndex());
00218 }
00219
00220
00221
00222
00223
00224
00225
00226 public void caseStaticFieldRef(StaticFieldRef v)
00227 {
00228 result = StaticFieldManager.get(v.getField()).getValues();
00229 }
00230
00231
00232
00233
00234
00235
00236
00237 public void caseThisRef(ThisRef v)
00238 {
00239 result = method.getThisValues();
00240 }
00241
00242
00243
00244
00245
00246
00247
00248 public void caseLocal(Local v)
00249 {
00250 result = method.getLocalNode(v).getValues();
00251 }
00252
00253
00254
00255
00256
00257
00258
00259 public void defaultCase(Object o)
00260 {
00261 cat.warn("ANALYSIS: We donot handle " + o + " of type " +
00262 o.getClass() + ".");
00263 }
00264 }
00265
00266
00267
00268
00269
00270
00271 public class StmtMethodPair {
00272
00273
00274
00275
00276 Stmt stmt;
00277
00278
00279
00280
00281
00282 SootMethod sm;
00283
00284
00285
00286
00287
00288
00289
00290 StmtMethodPair(Stmt s, SootMethod m)
00291 {
00292 stmt = s;
00293 sm = m;
00294 }
00295
00296
00297
00298
00299
00300
00301 public Stmt getStmt()
00302 {
00303 return stmt;
00304 }
00305
00306
00307
00308
00309
00310
00311 public SootMethod getSootMethod()
00312 {
00313 return sm;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 public boolean equals(Object o)
00326 {
00327 if (!(o instanceof StmtMethodPair)) return false;
00328 StmtMethodPair smp = (StmtMethodPair) o;
00329 return (stmt == smp.stmt && sm == smp.sm);
00330 }
00331
00332 public int hashCode() { return toString().hashCode(); }
00333 public String toString()
00334 {
00335 return sm + "::" + stmt;
00336 }
00337 }
00338
00339
00340
00341
00342
00343
00344 public class ExprStmtMethodTriple
00345 {
00346
00347
00348
00349
00350 Value expr;
00351
00352
00353
00354
00355
00356 StmtMethodPair smp;
00357
00358
00359
00360
00361
00362
00363
00364
00365 ExprStmtMethodTriple(Value expr, StmtMethodPair smp)
00366 {
00367 this.expr = expr;
00368 this.smp = smp;
00369 }
00370
00371
00372
00373
00374
00375
00376 public Value getExpr()
00377 {
00378 return expr;
00379 }
00380
00381
00382
00383
00384
00385
00386 public StmtMethodPair getStmtMethodPair()
00387 {
00388 return smp;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 public boolean equals(Object o)
00401 {
00402 if (!(o instanceof ExprStmtMethodTriple)) return false;
00403 ExprStmtMethodTriple esmt = (ExprStmtMethodTriple) o;
00404 return (expr == esmt.expr) && smp.equals(esmt.smp);
00405 }
00406
00407 public int hashCode() { return toString().hashCode(); }
00408 public String toString()
00409 {
00410 return smp + "--" + expr;
00411 }
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421 class classComparator implements Comparator
00422 {
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 public int compare(Object o1, Object o2)
00433 {
00434 if (o1 == o2)
00435 return -1;
00436 else if (((SootClass)o1).hasSuperClass())
00437 if (((SootClass)o1).getSuperClass() != (SootClass)o2)
00438 return compare(((SootClass)o1).getSuperClass(), o2);
00439 else
00440 return 0;
00441 else
00442 return 1;
00443 }
00444 }
00445
00446
00447
00448
00449
00450 private Analysis() { }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 public Collection getDefs(Value v, SootMethod enclosingMethod) {
00462 return getDefsOrUses(v, enclosingMethod, DEFS);
00463 }
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 private Collection getDefsOrUses(Value v, SootMethod enclosingMethod,
00477 int mode) {
00478 HashSet ud = new HashSet();
00479 Collection c = new ArrayList();
00480 Collection temp = new ArrayList();
00481 MethodVariant m = MethodVariantManager.select(enclosingMethod);
00482 FGNode f = null;
00483 if (v instanceof ThisRef) {
00484 temp.add(m.getThisNode());
00485 } else if (v instanceof ParameterRef) {
00486 temp.add(m.getParameterNode(((ParameterRef)v).getIndex()));
00487 } else if (v instanceof InstanceFieldRef) {
00488 temp.add(InstanceVariantManager
00489 .select(((InstanceFieldRef)v).getField()).getNode());
00490 } else if (v instanceof ArrayRef) {
00491 temp.addAll(m.getASTNode(v).getPreds());
00492 } else if (v instanceof StaticFieldRef) {
00493 temp.add(StaticFieldManager.select(((StaticFieldRef)v).getField()));
00494 } else if (v instanceof Local) {
00495 temp.add(m.getLocalNode((Local)v));
00496 }
00497
00498 if (mode == DEFS) {
00499 for (Iterator i = temp.iterator(); i.hasNext();) {
00500 c.addAll(((FGNode)i.next()).getPreds());
00501 }
00502 } else if (mode == USES) {
00503 for (Iterator i = temp.iterator(); i.hasNext();) {
00504 c.addAll(((FGNode)i.next()).getSuccs());
00505 }
00506 }
00507
00508 for (Iterator i = c.iterator(); i.hasNext();) {
00509 Stmt s = ((FGNodeAST)i.next()).getStmt();
00510 ud.add(getStmtMethodPair(s));
00511 }
00512 return ud;
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 private StmtMethodPair getStmtMethodPair(Stmt s)
00527 {
00528 StmtMethodPair smp = null;
00529 try {
00530 AnnotationManager am = CompilationManager.getAnnotationManager();
00531 Annotation a = am.getMethodAnnotationContainingAnnotation(
00532 am.getContainingAnnotation(s));
00533 if (a instanceof ConstructorDeclarationAnnotation) {
00534 smp = new StmtMethodPair(s,
00535 ((ConstructorDeclarationAnnotation)a)
00536 .getSootMethod());
00537 } else if (a instanceof MethodDeclarationAnnotation) {
00538 smp = new StmtMethodPair(s,
00539 ((MethodDeclarationAnnotation)a)
00540 .getSootMethod());
00541 }
00542 } catch (Exception e) {
00543 smp = null;
00544 e.printStackTrace();
00545 }
00546 return smp;
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 public Collection getUses(Value v, SootMethod enclosingMethod) {
00559 return getDefsOrUses(v, enclosingMethod, USES);
00560 }
00561
00562
00563
00564
00565
00566 public static Analysis init()
00567 {
00568 if (singleton == null) {
00569 singleton = new Analysis();
00570 cat = Category.getInstance(singleton.getClass().toString());
00571 }
00572 return singleton;
00573 }
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 public Collection invokeExprResolution(NonStaticInvokeExpr expr,
00585 SootMethod enclosingMethod)
00586 {
00587
00588 SootMethod sootMethod = expr.getMethod();
00589
00590 SootMethod methodImpl;
00591 SootClass sootClass;
00592 Collection classes = new ArrayList();
00593 ValueVariant variant;
00594 MethodVariant methodVariant;
00595 if (expr instanceof SpecialInvokeExpr) {
00596 classes.add(expr.getMethod().getDeclaringClass());
00597 } else {
00598
00599
00600
00601
00602 Local l = (Local)expr.getBase();
00603
00604
00605 for (Iterator variants =
00606 FA.summarizeLocalValueVariants(enclosingMethod,
00607 l).iterator();
00608 variants.hasNext();) {
00609 variant = (ValueVariant)variants.next();
00610 methodVariant = MethodVariantManager.select(enclosingMethod);
00611 if (variant.getClassToken()
00612 .equals(ClassTokenSimple.nullClassToken) ||
00613 variant.getClassToken()
00614 .equals(ClassTokenSimple.unknownClassToken)){
00615 cat.warn("BOFA: Null may be flowing into invocation site.");
00616 continue;
00617 }
00618
00619 sootClass =
00620 ((ClassTokenSimple)variant.getClassToken()).getSootClass();
00621
00622 methodImpl = MethodVariantManager.findDeclaringMethod(sootClass,
00623 sootMethod);
00624
00625 classes.add(methodImpl.getDeclaringClass());
00626 }
00627 }
00628
00629
00630
00631 classes = sortUnique(classes, new classComparator());
00632 return classes;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642 public boolean nullReference(Value v, SootMethod enclosingMethod)
00643 {
00644 RefValueSwitch temp = new RefValueSwitch();
00645 Iterator i = temp.build(v, enclosingMethod).iterator();
00646 boolean retval = false;
00647 for (; i.hasNext() && !retval; ) {
00648 Analysis.ExprStmtMethodTriple a =
00649 (Analysis.ExprStmtMethodTriple)i.next();
00650 retval = a.getExpr().getType().equals(NullType.v());
00651 }
00652 return retval;
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666 public Set referenceValueSet(Value v, SootMethod enclosingMethod)
00667 {
00668 RefValueSwitch temp = new RefValueSwitch();
00669 return temp.build(v, enclosingMethod);
00670 }
00671
00672
00673
00674
00675
00676
00677
00678
00679 static Collection sortUnique(Collection c, Comparator comparator)
00680 {
00681 int i, j, t = 0;
00682 Object temp;
00683 Object[] obj;
00684 LinkedList l = new LinkedList();
00685 obj = c.toArray();
00686 if (obj.length == 0) {
00687 return l;
00688 }
00689
00690 outer:
00691 for (i = 0; i < obj.length - 1; i++) {
00692 for (j = i + 1; j < obj.length; j++) {
00693
00694
00695 if (obj[i] == obj[j])
00696 continue outer;
00697 t = comparator.compare(obj[i], obj[j]);
00698 if (t != 0) {
00699 temp = obj[j];
00700 obj[j] = obj[i];
00701 obj[i] = temp;
00702 }
00703 }
00704 if (t != -1)
00705 l.add(obj[i]);
00706 }
00707 l.add(obj[obj.length - 1]);
00708 return l;
00709 }
00710 }