/** * collect the putstatic instructions in the call graph as {@link PathEdge} seeds for the * analysis */ private Collection<PathEdge<BasicBlockInContext<IExplodedBasicBlock>>> collectInitialSeeds() { Collection<PathEdge<BasicBlockInContext<IExplodedBasicBlock>>> result = HashSetFactory.make(); for (BasicBlockInContext<IExplodedBasicBlock> bb : supergraph) { IExplodedBasicBlock ebb = bb.getDelegate(); SSAInstruction instruction = ebb.getInstruction(); if (instruction instanceof SSAPutInstruction) { SSAPutInstruction putInstr = (SSAPutInstruction) instruction; if (putInstr.isStatic()) { final CGNode cgNode = bb.getNode(); Pair<CGNode, Integer> fact = Pair.make(cgNode, ebb.getFirstInstructionIndex()); int factNum = domain.add(fact); BasicBlockInContext<IExplodedBasicBlock> fakeEntry = getFakeEntry(cgNode); // note that the fact number used for the source of this path edge doesn't really matter result.add(PathEdge.createPathEdge(fakeEntry, factNum, bb, factNum)); } } } return result; }
/** flow function for normal intraprocedural edges */ public IUnaryFlowFunction getNormalFlowFunction( final BasicBlockInContext<IExplodedBasicBlock> src, BasicBlockInContext<IExplodedBasicBlock> dest) { final IExplodedBasicBlock ebb = src.getDelegate(); SSAInstruction instruction = ebb.getInstruction(); if (instruction instanceof SSAPutInstruction) { final SSAPutInstruction putInstr = (SSAPutInstruction) instruction; if (putInstr.isStatic()) { return new IUnaryFlowFunction() { public IntSet getTargets(int d1) { // first, gen this statement int factNum = domain.getMappedIndex(Pair.make(src.getNode(), ebb.getFirstInstructionIndex())); assert factNum != -1; MutableSparseIntSet result = MutableSparseIntSet.makeEmpty(); result.add(factNum); // if incoming statement is some different statement that defs the same static field, // kill it; otherwise, keep it if (d1 != factNum) { IField staticField = cha.resolveField(putInstr.getDeclaredField()); assert staticField != null; Pair<CGNode, Integer> otherPutInstrAndNode = domain.getMappedObject(d1); SSAPutInstruction otherPutInstr = (SSAPutInstruction) otherPutInstrAndNode.fst.getIR() .getInstructions()[otherPutInstrAndNode.snd]; IField otherStaticField = cha.resolveField(otherPutInstr.getDeclaredField()); if (!staticField.equals(otherStaticField)) { result.add(d1); } } return result; } public String toString() { return "Reaching Defs Normal Flow"; } }; } } // identity function when src block isn't for a putstatic return IdentityFlowFunction.identity(); }
@Override public boolean isExit(BasicBlockInContext<IExplodedBasicBlock> n) { return n.getDelegate().isExitBlock(); }
@Override public boolean isCall(BasicBlockInContext<IExplodedBasicBlock> n) { return n.getDelegate().getInstruction() instanceof SSAAbstractInvokeInstruction; }
@Override public int getLocalBlockNumber(BasicBlockInContext<IExplodedBasicBlock> n) { return n.getDelegate().getNumber(); }
/** * we use the entry block of the CGNode as the fake entry when propagating from callee to caller * with unbalanced parens */ public BasicBlockInContext<IExplodedBasicBlock> getFakeEntry( BasicBlockInContext<IExplodedBasicBlock> node) { final CGNode cgNode = node.getNode(); return getFakeEntry(cgNode); }