/** * Constructor. * * @param cfg * the CFG to perform the reverse depth first search on */ public ReverseDepthFirstSearch(CFG cfg) { super(cfg); this.firstRoot = cfg.getExit(); }
/** * Get the exit block for the subroutine's CFG. */ public BasicBlock getExit() { return cfgSub.getExit(); }
@Override public void visitBasicBlock(BasicBlock basicBlock) { curBlock = basicBlock; if (COMPUTE_TRANSFERS && basicBlock == cfg.getExit()) { // We're at the CFG exit. if (adjustedLeakCount == 1) { applyPossibleObligationTransfers(); } } }
/** * Get the "logical" entry block of the CFG. For forward analyses, this is * the entry block. For backward analyses, this is the exit block. */ private BasicBlock logicalEntryBlock() { return isForwards ? cfg.getEntry() : cfg.getExit(); }
@Override public void edgeTransfer(Edge edge, ReturnPathType fact) { // The edges leading into the exit block create the "seed" values // for the analysis. The exception edges create values indicating // that a normal (non-exception) return is not possible, // while the non-exception edges create values indicating that // a normal return is possible. if (edge.getTarget() == cfg.getExit()) { fact.setCanReturnNormally(!edge.isExceptionEdge()); } }
if (last.getTarget() == cfg.getExit()) { pathList.add(new LinkedList<>(partialPath)); return;
@Override public void inspectResult(ClassContext classContext, MethodGen methodGen, CFG cfg, Dataflow<ResourceValueFrame, ResourceValueAnalysis<Stream>> dataflow, Stream stream) { if (DEBUG) { System.out.printf("Result for %s in %s%n", stream, methodGen); dataflow.dumpDataflow(dataflow.getAnalysis()); } ResourceValueFrame exitFrame = dataflow.getResultFact(cfg.getExit()); int exitStatus = exitFrame.getStatus(); if (exitStatus == ResourceValueFrame.OPEN || exitStatus == ResourceValueFrame.OPEN_ON_EXCEPTION_PATH) { // FIXME: Stream object should be queried for the // priority. String bugType = stream.getBugType(); int priority = NORMAL_PRIORITY; if (exitStatus == ResourceValueFrame.OPEN_ON_EXCEPTION_PATH) { bugType += "_EXCEPTION_PATH"; priority = LOW_PRIORITY; } potentialOpenStreamList.add(new PotentialOpenStream(bugType, priority, stream)); } else if (exitStatus == ResourceValueFrame.CLOSED) { // Remember that this stream was closed on all paths. // Later, we will mark all of the streams in its equivalence class // as having been closed. stream.setClosed(); } }
StateSet factAtExit = dataflow.getResultFact(cfg.getExit()); for (Iterator<State> i = factAtExit.stateIterator(); i.hasNext();) { State state = i.next();
private void checkStateForLeakedObligations(State state, Map<Obligation, State> leakedObligationMap) throws IllegalStateException { if (DEBUG) { Path path = state.getPath(); if (path.getLength() > 0 && path.getBlockIdAt(path.getLength() - 1) != cfg.getExit().getLabel()) { throw new IllegalStateException("path " + path + " at cfg exit has no label for exit block"); } } for (int id = 0; id < database.getFactory().getMaxObligationTypes(); ++id) { Obligation obligation = database.getFactory().getObligationById(id); // If the raw count produced by the analysis // for this obligation type is 0, // assume everything is ok on this state's path. int rawLeakCount = state.getObligationSet().getCount(id); if (rawLeakCount == 0) { continue; } // Apply the false-positive suppression heuristics int leakCount = getAdjustedLeakCount(state, id); if (leakCount > 0) { leakedObligationMap.put(obligation, state); } // TODO: if the leak count is less than 0, then a nonexistent // resource was closed } }
ResourceValueFrame exitFrame = dataflow.getResultFact(cfg.getExit()); if (DEBUG) { System.out.println("Resource value at exit: " + exitFrame);
/** * Inline all JSR subroutines into the top-level subroutine. This produces a * complete CFG for the entire method, in which all JSR subroutines are * inlined. * * @return the CFG for the method */ private CFG inlineAll() throws CFGBuilderException { CFG result = new CFG(); Context rootContext = new Context(null, topLevelSubroutine, result); rootContext.mapBlock(topLevelSubroutine.getEntry(), result.getEntry()); rootContext.mapBlock(topLevelSubroutine.getExit(), result.getExit()); BasicBlock resultStartBlock = rootContext.getBlock(topLevelSubroutine.getStartBlock()); result.createEdge(result.getEntry(), resultStartBlock, START_EDGE); inline(rootContext); return result; }
/** * Get the exit block for the subroutine's CFG. */ public BasicBlock getExit() { return cfgSub.getExit(); }
/** * Constructor. * * @param cfg * the CFG to perform the reverse depth first search on */ public ReverseDepthFirstSearch(CFG cfg) { super(cfg); this.firstRoot = cfg.getExit(); }
/** * Get the "logical" entry block of the CFG. For forward analyses, this is * the entry block. For backward analyses, this is the exit block. */ private BasicBlock logicalEntryBlock() { return isForwards ? cfg.getEntry() : cfg.getExit(); }
@Override public void visitBasicBlock(BasicBlock basicBlock) { curBlock = basicBlock; if (COMPUTE_TRANSFERS && basicBlock == cfg.getExit()) { // We're at the CFG exit. if (adjustedLeakCount == 1) { applyPossibleObligationTransfers(); } } }
@Override public void edgeTransfer(Edge edge, ReturnPathType fact) { // The edges leading into the exit block create the "seed" values // for the analysis. The exception edges create values indicating // that a normal (non-exception) return is not possible, // while the non-exception edges create values indicating that // a normal return is possible. if (edge.getTarget() == cfg.getExit()) { fact.setCanReturnNormally(!edge.isExceptionEdge()); } }
@Override public void inspectResult(ClassContext classContext, MethodGen methodGen, CFG cfg, Dataflow<ResourceValueFrame, ResourceValueAnalysis<Stream>> dataflow, Stream stream) { if (DEBUG) { System.out.printf("Result for %s in %s%n", stream, methodGen); dataflow.dumpDataflow(dataflow.getAnalysis()); } ResourceValueFrame exitFrame = dataflow.getResultFact(cfg.getExit()); int exitStatus = exitFrame.getStatus(); if (exitStatus == ResourceValueFrame.OPEN || exitStatus == ResourceValueFrame.OPEN_ON_EXCEPTION_PATH) { // FIXME: Stream object should be queried for the // priority. String bugType = stream.getBugType(); int priority = NORMAL_PRIORITY; if (exitStatus == ResourceValueFrame.OPEN_ON_EXCEPTION_PATH) { bugType += "_EXCEPTION_PATH"; priority = LOW_PRIORITY; } potentialOpenStreamList.add(new PotentialOpenStream(bugType, priority, stream)); } else if (exitStatus == ResourceValueFrame.CLOSED) { // Remember that this stream was closed on all paths. // Later, we will mark all of the streams in its equivalence class // as having been closed. stream.setClosed(); } }
private void checkStateForLeakedObligations(State state, Map<Obligation, State> leakedObligationMap) throws IllegalStateException { if (DEBUG) { Path path = state.getPath(); if (path.getLength() > 0 && path.getBlockIdAt(path.getLength() - 1) != cfg.getExit().getLabel()) { throw new IllegalStateException("path " + path + " at cfg exit has no label for exit block"); } } for (int id = 0; id < database.getFactory().getMaxObligationTypes(); ++id) { Obligation obligation = database.getFactory().getObligationById(id); // If the raw count produced by the analysis // for this obligation type is 0, // assume everything is ok on this state's path. int rawLeakCount = state.getObligationSet().getCount(id); if (rawLeakCount == 0) { continue; } // Apply the false-positive suppression heuristics int leakCount = getAdjustedLeakCount(state, id); if (leakCount > 0) { leakedObligationMap.put(obligation, state); } // TODO: if the leak count is less than 0, then a nonexistent // resource was closed } }
/** * Inline all JSR subroutines into the top-level subroutine. This produces a * complete CFG for the entire method, in which all JSR subroutines are * inlined. * * @return the CFG for the method */ private CFG inlineAll() throws CFGBuilderException { CFG result = new CFG(); Context rootContext = new Context(null, topLevelSubroutine, result); rootContext.mapBlock(topLevelSubroutine.getEntry(), result.getEntry()); rootContext.mapBlock(topLevelSubroutine.getExit(), result.getExit()); BasicBlock resultStartBlock = rootContext.getBlock(topLevelSubroutine.getStartBlock()); result.createEdge(result.getEntry(), resultStartBlock, START_EDGE); inline(rootContext); return result; }