1 19 20 package edu.umd.cs.findbugs.detect; 21 22 import java.util.HashSet ; 23 import java.util.Iterator ; 24 import java.util.Set ; 25 26 import org.apache.bcel.classfile.Method; 27 import org.apache.bcel.generic.MethodGen; 28 29 import edu.umd.cs.findbugs.BugInstance; 30 import edu.umd.cs.findbugs.BugReporter; 31 import edu.umd.cs.findbugs.Detector; 32 import edu.umd.cs.findbugs.SystemProperties; 33 import edu.umd.cs.findbugs.ba.CFG; 34 import edu.umd.cs.findbugs.ba.CFGBuilderException; 35 import edu.umd.cs.findbugs.ba.ClassContext; 36 import edu.umd.cs.findbugs.ba.Dataflow; 37 import edu.umd.cs.findbugs.ba.DataflowAnalysisException; 38 import edu.umd.cs.findbugs.ba.DataflowCFGPrinter; 39 import edu.umd.cs.findbugs.ba.DepthFirstSearch; 40 import edu.umd.cs.findbugs.ba.SignatureConverter; 41 import edu.umd.cs.findbugs.ba.obl.Obligation; 42 import edu.umd.cs.findbugs.ba.obl.ObligationAnalysis; 43 import edu.umd.cs.findbugs.ba.obl.ObligationFactory; 44 import edu.umd.cs.findbugs.ba.obl.PolicyDatabase; 45 import edu.umd.cs.findbugs.ba.obl.State; 46 import edu.umd.cs.findbugs.ba.obl.StateSet; 47 import edu.umd.cs.findbugs.ba.type.TypeDataflow; 48 49 60 public class FindUnsatisfiedObligation implements Detector { 61 62 private static final boolean ENABLE = SystemProperties.getBoolean("oa.enable"); 63 private static final boolean DEBUG = SystemProperties.getBoolean("oa.debug"); 64 private static final boolean DEBUG_PRINTCFG = SystemProperties.getBoolean("oa.printcfg"); 65 private static final String DEBUG_METHOD = SystemProperties.getProperty("oa.method"); 66 67 private BugReporter bugReporter; 68 private ObligationFactory factory; 69 private PolicyDatabase database; 70 71 public FindUnsatisfiedObligation(BugReporter bugReporter) { 72 this.bugReporter = bugReporter; 73 this.factory = new ObligationFactory(); 74 this.database = buildDatabase(); 75 } 76 77 80 public void visitClassContext(ClassContext classContext) { 81 if (!ENABLE) { 82 return; 83 } 84 85 87 Method[] methodList = classContext.getJavaClass().getMethods(); 88 for (Method method : methodList) { 89 if (DEBUG_METHOD != null && !method.getName().equals(DEBUG_METHOD)) 90 continue; 91 92 MethodGen methodGen = classContext.getMethodGen(method); 93 94 if (methodGen != null) { 95 analyzeMethod(classContext, method); 97 } 98 } 99 } 100 101 107 private void analyzeMethod(ClassContext classContext, Method method) { 108 MethodGen methodGen = classContext.getMethodGen(method); 109 if (methodGen == null) return; 110 if (DEBUG) { 111 System.out.println("*** Analyzing method " + 112 SignatureConverter.convertMethodSignature(methodGen)); 113 } 114 115 try { 116 CFG cfg = classContext.getCFG(method); 117 DepthFirstSearch dfs = classContext.getDepthFirstSearch(method); 118 TypeDataflow typeDataflow = classContext.getTypeDataflow(method); 119 assert typeDataflow != null; 120 121 ObligationAnalysis analysis = 122 new ObligationAnalysis(dfs, typeDataflow, methodGen, factory, database, bugReporter); 123 Dataflow<StateSet, ObligationAnalysis> dataflow = 124 new Dataflow<StateSet, ObligationAnalysis>(cfg, analysis); 125 126 dataflow.execute(); 127 128 if (DEBUG_PRINTCFG) { 129 System.out.println("Dataflow CFG:"); 130 DataflowCFGPrinter.printCFG(dataflow, System.out); 131 } 132 133 StateSet factAtExit = dataflow.getStartFact(cfg.getExit()); 135 Set <Obligation> leakedObligationSet = new HashSet <Obligation>(); 136 for (Iterator <State> i = factAtExit.stateIterator(); i.hasNext();) { 137 State state = i.next(); 138 for (int id = 0; id < factory.getMaxObligationTypes(); ++id) { 139 if (state.getObligationSet().getCount(id) > 0) { 140 leakedObligationSet.add(factory.getObligationById(id)); 141 } 142 } 143 } 144 145 for (Obligation obligation : leakedObligationSet) { 146 bugReporter.reportBug(new BugInstance(this, "OS_OPEN_STREAM", NORMAL_PRIORITY) 147 .addClassAndMethod(methodGen, classContext.getJavaClass().getSourceFileName()) 148 .addClass(obligation.getClassName()).describe("CLASS_REFTYPE") 149 ); 150 } 151 } catch (CFGBuilderException e) { 152 bugReporter.logError( 153 "Error building CFG for " + 154 SignatureConverter.convertMethodSignature(methodGen), e); 155 } catch (DataflowAnalysisException e) { 156 bugReporter.logError( 157 "ObligationAnalysis error while analyzing " + 158 SignatureConverter.convertMethodSignature(methodGen), e); 159 } 160 } 161 162 165 public void report() { 166 } 168 169 174 private PolicyDatabase buildDatabase() { 175 PolicyDatabase result = new PolicyDatabase(); 176 177 Obligation inputStreamObligation = factory.addObligation("java.io.InputStream"); 179 Obligation outputStreamObligation = factory.addObligation("java.io.OutputStream"); 180 181 result.addEntry("java.io.FileInputStream", "<init>", "(Ljava/lang/String;)V", false, 184 PolicyDatabase.ADD, inputStreamObligation); 185 result.addEntry("java.io.FileOutputStream", "<init>", "(Ljava/lang/String;)V", false, 186 PolicyDatabase.ADD, outputStreamObligation); 187 result.addEntry("java.io.InputStream", "close", "()V", false, 188 PolicyDatabase.DEL, inputStreamObligation); 189 result.addEntry("java.io.OutputStream", "close", "()V", false, 190 PolicyDatabase.DEL, outputStreamObligation); 191 192 return result; 193 } 194 195 } 196 | Popular Tags |