code cleanup of nullpointer analysis
- replace tabs with whitespace - adjust documentation to refer to renamed stuff
This commit is contained in:
parent
acde4add28
commit
34674387e6
|
@ -32,7 +32,7 @@ public interface ExceptionPruningAnalysis<I, T extends IBasicBlock<I>> {
|
|||
* @throws CancelException
|
||||
* Thrown if the user requested cancellation through the progress
|
||||
* monitor.
|
||||
*/
|
||||
*/
|
||||
int compute(IProgressMonitor progress) throws UnsoundGraphException, CancelException;
|
||||
|
||||
/**
|
||||
|
@ -57,7 +57,7 @@ public interface ExceptionPruningAnalysis<I, T extends IBasicBlock<I>> {
|
|||
/**
|
||||
* Returns the state of a node. The node has to be part of the cfg.
|
||||
* @param bb Node
|
||||
* @return EdgeState
|
||||
* @return NullPointerState
|
||||
*/
|
||||
NullPointerState getState(T bb);
|
||||
|
||||
|
|
|
@ -33,18 +33,12 @@ public class ExplodedCFGNullPointerAnalysis implements ExceptionPruningAnalysis<
|
|||
this.initialState = (paramState == null ? ParameterState.createDefault(ir.getMethod()) : paramState);
|
||||
this.mState = (mState == null ? MethodState.DEFAULT : mState);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see jsdg.exceptions.ExceptionPrunedCFGAnalysis#getOriginal()
|
||||
*/
|
||||
public ControlFlowGraph<SSAInstruction, IExplodedBasicBlock> getOriginal() {
|
||||
return ExplodedControlFlowGraph.make(ir);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.cfg.exc.ExceptionPrunedCFGAnalysis#compute(com.ibm.wala.util.MonitorUtil.IProgressMonitor)
|
||||
*/
|
||||
public int compute(IProgressMonitor progress) throws UnsoundGraphException, CancelException {
|
||||
ControlFlowGraph<SSAInstruction, IExplodedBasicBlock> orig = getOriginal();
|
||||
ControlFlowGraph<SSAInstruction, IExplodedBasicBlock> orig = ExplodedControlFlowGraph.make(ir);
|
||||
|
||||
intra = new IntraprocNullPointerAnalysis<IExplodedBasicBlock>(ir, orig, ignoredExceptions, initialState, mState);
|
||||
intra.run(progress);
|
||||
|
@ -53,14 +47,14 @@ public class ExplodedCFGNullPointerAnalysis implements ExceptionPruningAnalysis<
|
|||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see jsdg.exceptions.ExceptionPrunedCFGAnalysis#getPruned()
|
||||
* @see jsdg.exceptions.ExceptionPrunedCFGAnalysis#getCFG()
|
||||
*/
|
||||
public ControlFlowGraph<SSAInstruction, IExplodedBasicBlock> getCFG() {
|
||||
if (intra == null) {
|
||||
throw new IllegalStateException("Run compute(IProgressMonitor) first.");
|
||||
}
|
||||
|
||||
return intra.getPrunedCfg();
|
||||
return intra.getPrunedCFG();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -71,7 +65,7 @@ public class ExplodedCFGNullPointerAnalysis implements ExceptionPruningAnalysis<
|
|||
throw new IllegalStateException("Run compute(IProgressMonitor) first.");
|
||||
}
|
||||
|
||||
ControlFlowGraph<SSAInstruction, IExplodedBasicBlock> cfg = intra.getPrunedCfg();
|
||||
ControlFlowGraph<SSAInstruction, IExplodedBasicBlock> cfg = intra.getPrunedCFG();
|
||||
|
||||
boolean hasException = false;
|
||||
for (IExplodedBasicBlock bb : cfg) {
|
||||
|
|
|
@ -51,197 +51,197 @@ public class IntraprocNullPointerAnalysis<T extends ISSABasicBlock> {
|
|||
|
||||
private NullPointerSolver<T> solver;
|
||||
|
||||
private final Set<TypeReference> ignoreExceptions;
|
||||
private final IR ir;
|
||||
private final ControlFlowGraph<SSAInstruction, T> cfg;
|
||||
private final int maxVarNum;
|
||||
private int deletedEdges;
|
||||
private ControlFlowGraph<SSAInstruction, T> pruned = null;
|
||||
private final Set<TypeReference> ignoreExceptions;
|
||||
private final IR ir;
|
||||
private final ControlFlowGraph<SSAInstruction, T> cfg;
|
||||
private final int maxVarNum;
|
||||
private int deletedEdges;
|
||||
private ControlFlowGraph<SSAInstruction, T> pruned = null;
|
||||
|
||||
private final ParameterState initialState;
|
||||
private final MethodState mState;
|
||||
private final ParameterState initialState;
|
||||
private final MethodState mState;
|
||||
|
||||
IntraprocNullPointerAnalysis(IR ir, ControlFlowGraph<SSAInstruction, T> cfg,
|
||||
TypeReference[] ignoreExceptions, ParameterState initialState, MethodState mState) {
|
||||
this.cfg = cfg;
|
||||
this.ir = ir;
|
||||
if (ir == null || ir.isEmptyIR()) {
|
||||
maxVarNum = -1;
|
||||
} else {
|
||||
maxVarNum = ir.getSymbolTable().getMaxValueNumber();
|
||||
}
|
||||
|
||||
this.ignoreExceptions = new HashSet<TypeReference>();
|
||||
|
||||
if (ignoreExceptions != null) {
|
||||
for (TypeReference tRef : ignoreExceptions) {
|
||||
this.ignoreExceptions.add(tRef);
|
||||
}
|
||||
}
|
||||
|
||||
this.initialState = initialState;
|
||||
this.mState = mState;
|
||||
}
|
||||
IntraprocNullPointerAnalysis(IR ir, ControlFlowGraph<SSAInstruction, T> cfg,
|
||||
TypeReference[] ignoreExceptions, ParameterState initialState, MethodState mState) {
|
||||
this.cfg = cfg;
|
||||
this.ir = ir;
|
||||
if (ir == null || ir.isEmptyIR()) {
|
||||
maxVarNum = -1;
|
||||
} else {
|
||||
maxVarNum = ir.getSymbolTable().getMaxValueNumber();
|
||||
}
|
||||
|
||||
this.ignoreExceptions = new HashSet<TypeReference>();
|
||||
|
||||
if (ignoreExceptions != null) {
|
||||
for (TypeReference tRef : ignoreExceptions) {
|
||||
this.ignoreExceptions.add(tRef);
|
||||
}
|
||||
}
|
||||
|
||||
this.initialState = initialState;
|
||||
this.mState = mState;
|
||||
}
|
||||
|
||||
void run(IProgressMonitor progress) throws CancelException {
|
||||
if (pruned == null) {
|
||||
if (ir == null || ir.isEmptyIR()) {
|
||||
pruned = cfg;
|
||||
} else {
|
||||
NullPointerFrameWork<T> problem = new NullPointerFrameWork<T>(cfg, ir);
|
||||
int[] paramValNum = ir.getParameterValueNumbers();
|
||||
|
||||
solver = new NullPointerSolver<T>(problem, maxVarNum, paramValNum, initialState);
|
||||
|
||||
if (solver.solve(progress)) {
|
||||
// we were able to remove some exceptions
|
||||
Graph<T> deleted = createDeletedGraph(solver);
|
||||
for (T node : deleted) {
|
||||
deletedEdges += deleted.getSuccNodeCount(node);
|
||||
}
|
||||
NegativeGraphFilter<T> filter = new NegativeGraphFilter<T>(deleted);
|
||||
|
||||
pruned = PrunedCFG.make(cfg, filter);
|
||||
} else {
|
||||
pruned = cfg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Graph<T> createDeletedGraph(NullPointerSolver<T> solver) {
|
||||
NegativeCFGBuilderVisitor nCFGbuilder = new NegativeCFGBuilderVisitor(solver);
|
||||
for (T bb : cfg) {
|
||||
nCFGbuilder.work(bb);
|
||||
}
|
||||
|
||||
Graph<T> deleted = nCFGbuilder.getNegativeCFG();
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
ControlFlowGraph<SSAInstruction, T> getPrunedCfg() {
|
||||
if (pruned == null) {
|
||||
throw new IllegalStateException("Run analysis first! (call run())");
|
||||
}
|
||||
|
||||
return pruned;
|
||||
}
|
||||
|
||||
int getNumberOfDeletedEdges() {
|
||||
if (pruned == null) {
|
||||
throw new IllegalStateException("Run analysis first! (call run())");
|
||||
}
|
||||
|
||||
return deletedEdges;
|
||||
}
|
||||
|
||||
public NullPointerState getState(T block) {
|
||||
assert pruned != null || solver != null : "No solver initialized for method " + ir.getMethod().toString();
|
||||
if (pruned != null && solver == null) {
|
||||
// empty IR ... so states have not changed and we can return the initial state as a save approximation
|
||||
return new NullPointerState(maxVarNum, ir.getSymbolTable(), initialState);
|
||||
} else {
|
||||
return solver.getIn(block);
|
||||
}
|
||||
}
|
||||
|
||||
private class NullPointerSolver<B extends ISSABasicBlock> extends DataflowSolver<B, NullPointerState> {
|
||||
void run(IProgressMonitor progress) throws CancelException {
|
||||
if (pruned == null) {
|
||||
if (ir == null || ir.isEmptyIR()) {
|
||||
pruned = cfg;
|
||||
} else {
|
||||
NullPointerFrameWork<T> problem = new NullPointerFrameWork<T>(cfg, ir);
|
||||
int[] paramValNum = ir.getParameterValueNumbers();
|
||||
|
||||
solver = new NullPointerSolver<T>(problem, maxVarNum, paramValNum, initialState);
|
||||
|
||||
if (solver.solve(progress)) {
|
||||
// we were able to remove some exceptions
|
||||
Graph<T> deleted = createDeletedGraph(solver);
|
||||
for (T node : deleted) {
|
||||
deletedEdges += deleted.getSuccNodeCount(node);
|
||||
}
|
||||
NegativeGraphFilter<T> filter = new NegativeGraphFilter<T>(deleted);
|
||||
|
||||
pruned = PrunedCFG.make(cfg, filter);
|
||||
} else {
|
||||
pruned = cfg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Graph<T> createDeletedGraph(NullPointerSolver<T> solver) {
|
||||
NegativeCFGBuilderVisitor nCFGbuilder = new NegativeCFGBuilderVisitor(solver);
|
||||
for (T bb : cfg) {
|
||||
nCFGbuilder.work(bb);
|
||||
}
|
||||
|
||||
Graph<T> deleted = nCFGbuilder.getNegativeCFG();
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
ControlFlowGraph<SSAInstruction, T> getPrunedCFG() {
|
||||
if (pruned == null) {
|
||||
throw new IllegalStateException("Run analysis first! (call run())");
|
||||
}
|
||||
|
||||
return pruned;
|
||||
}
|
||||
|
||||
int getNumberOfDeletedEdges() {
|
||||
if (pruned == null) {
|
||||
throw new IllegalStateException("Run analysis first! (call run())");
|
||||
}
|
||||
|
||||
return deletedEdges;
|
||||
}
|
||||
|
||||
public NullPointerState getState(T block) {
|
||||
assert pruned != null || solver != null : "No solver initialized for method " + ir.getMethod().toString();
|
||||
if (pruned != null && solver == null) {
|
||||
// empty IR ... so states have not changed and we can return the initial state as a save approximation
|
||||
return new NullPointerState(maxVarNum, ir.getSymbolTable(), initialState);
|
||||
} else {
|
||||
return solver.getIn(block);
|
||||
}
|
||||
}
|
||||
|
||||
private class NullPointerSolver<B extends ISSABasicBlock> extends DataflowSolver<B, NullPointerState> {
|
||||
|
||||
private final int maxVarNum;
|
||||
private final ParameterState parameterState;
|
||||
private final int maxVarNum;
|
||||
private final ParameterState parameterState;
|
||||
|
||||
private NullPointerSolver(NullPointerFrameWork<B> problem, int maxVarNum, int[] paramVarNum) {
|
||||
this(problem, maxVarNum, paramVarNum, null);
|
||||
}
|
||||
|
||||
private NullPointerSolver(NullPointerFrameWork<B> problem, int maxVarNum, int[] paramVarNum, ParameterState initialState) {
|
||||
super(problem);
|
||||
this.maxVarNum = maxVarNum;
|
||||
this.parameterState = initialState;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.DataflowSolver#makeEdgeVariable(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected NullPointerState makeEdgeVariable(B src, B dst) {
|
||||
return new NullPointerState(maxVarNum, ir.getSymbolTable(), parameterState);
|
||||
}
|
||||
private NullPointerSolver(NullPointerFrameWork<B> problem, int maxVarNum, int[] paramVarNum) {
|
||||
this(problem, maxVarNum, paramVarNum, null);
|
||||
}
|
||||
|
||||
private NullPointerSolver(NullPointerFrameWork<B> problem, int maxVarNum, int[] paramVarNum, ParameterState initialState) {
|
||||
super(problem);
|
||||
this.maxVarNum = maxVarNum;
|
||||
this.parameterState = initialState;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.DataflowSolver#makeEdgeVariable(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected NullPointerState makeEdgeVariable(B src, B dst) {
|
||||
return new NullPointerState(maxVarNum, ir.getSymbolTable(), parameterState);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.DataflowSolver#makeNodeVariable(java.lang.Object, boolean)
|
||||
*/
|
||||
@Override
|
||||
protected NullPointerState makeNodeVariable(B n, boolean IN) {
|
||||
return new NullPointerState(maxVarNum, ir.getSymbolTable(), parameterState);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.DataflowSolver#makeNodeVariable(java.lang.Object, boolean)
|
||||
*/
|
||||
@Override
|
||||
protected NullPointerState makeNodeVariable(B n, boolean IN) {
|
||||
return new NullPointerState(maxVarNum, ir.getSymbolTable(), parameterState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NullPointerState[] makeStmtRHS(int size) {
|
||||
return new NullPointerState[size];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class NegativeCFGBuilderVisitor implements IVisitor {
|
||||
|
||||
}
|
||||
|
||||
private class NegativeCFGBuilderVisitor implements IVisitor {
|
||||
|
||||
private final Graph<T> deleted;
|
||||
private final NullPointerSolver<T> solver;
|
||||
|
||||
private NegativeCFGBuilderVisitor(NullPointerSolver<T> solver) {
|
||||
this.solver = solver;
|
||||
this.deleted = new SparseNumberedGraph<T>(2);
|
||||
for (T bb : cfg) {
|
||||
deleted.addNode(bb);
|
||||
}
|
||||
}
|
||||
|
||||
private NullPointerState currentState;
|
||||
private T currentBlock;
|
||||
|
||||
public void work(T bb) {
|
||||
if (bb == null) {
|
||||
throw new IllegalArgumentException("Null not allowed");
|
||||
} else if (!cfg.containsNode(bb)) {
|
||||
throw new IllegalArgumentException("Block not part of current CFG");
|
||||
}
|
||||
|
||||
SSAInstruction instr = NullPointerTransferFunctionProvider.getRelevantInstruction(bb);
|
||||
|
||||
if (instr != null) {
|
||||
currentState = solver.getIn(bb);
|
||||
currentBlock = bb;
|
||||
instr.visit(this);
|
||||
currentState = null;
|
||||
currentBlock = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Graph<T> getNegativeCFG() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* We have to be careful here. If the invoke instruction can not throw a NullPointerException,
|
||||
* because the reference object is not null, the method itself may throw a NullPointerException.
|
||||
* So we can only remove the edge if the method itself throws no exception.
|
||||
*/
|
||||
private boolean isOnlyNullPointerExc(SSAInstruction instr) {
|
||||
assert instr.isPEI();
|
||||
|
||||
if (instr instanceof SSAAbstractInvokeInstruction) {
|
||||
return mState != null && !mState.throwsException((SSAAbstractInvokeInstruction) instr);
|
||||
} else {
|
||||
Collection<TypeReference> exc = instr.getExceptionTypes();
|
||||
Set<TypeReference> myExcs = new HashSet<TypeReference>(exc);
|
||||
myExcs.removeAll(ignoreExceptions);
|
||||
|
||||
return myExcs.size() == 1 && myExcs.contains(TypeReference.JavaLangNullPointerException);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean noExceptions(SSAInstruction instr) {
|
||||
private final Graph<T> deleted;
|
||||
private final NullPointerSolver<T> solver;
|
||||
|
||||
private NegativeCFGBuilderVisitor(NullPointerSolver<T> solver) {
|
||||
this.solver = solver;
|
||||
this.deleted = new SparseNumberedGraph<T>(2);
|
||||
for (T bb : cfg) {
|
||||
deleted.addNode(bb);
|
||||
}
|
||||
}
|
||||
|
||||
private NullPointerState currentState;
|
||||
private T currentBlock;
|
||||
|
||||
public void work(T bb) {
|
||||
if (bb == null) {
|
||||
throw new IllegalArgumentException("Null not allowed");
|
||||
} else if (!cfg.containsNode(bb)) {
|
||||
throw new IllegalArgumentException("Block not part of current CFG");
|
||||
}
|
||||
|
||||
SSAInstruction instr = NullPointerTransferFunctionProvider.getRelevantInstruction(bb);
|
||||
|
||||
if (instr != null) {
|
||||
currentState = solver.getIn(bb);
|
||||
currentBlock = bb;
|
||||
instr.visit(this);
|
||||
currentState = null;
|
||||
currentBlock = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Graph<T> getNegativeCFG() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* We have to be careful here. If the invoke instruction can not throw a NullPointerException,
|
||||
* because the reference object is not null, the method itself may throw a NullPointerException.
|
||||
* So we can only remove the edge if the method itself throws no exception.
|
||||
*/
|
||||
private boolean isOnlyNullPointerExc(SSAInstruction instr) {
|
||||
assert instr.isPEI();
|
||||
|
||||
if (instr instanceof SSAAbstractInvokeInstruction) {
|
||||
return mState != null && !mState.throwsException((SSAAbstractInvokeInstruction) instr);
|
||||
} else {
|
||||
Collection<TypeReference> exc = instr.getExceptionTypes();
|
||||
Set<TypeReference> myExcs = new HashSet<TypeReference>(exc);
|
||||
myExcs.removeAll(ignoreExceptions);
|
||||
|
||||
return myExcs.size() == 1 && myExcs.contains(TypeReference.JavaLangNullPointerException);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean noExceptions(SSAInstruction instr) {
|
||||
assert instr.isPEI();
|
||||
|
||||
if (instr instanceof SSAAbstractInvokeInstruction) {
|
||||
|
@ -253,23 +253,23 @@ public class IntraprocNullPointerAnalysis<T extends ISSABasicBlock> {
|
|||
|
||||
return myExcs.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeImpossibleSuccessors(SSAInstruction instr, int varNum) {
|
||||
if (isOnlyNullPointerExc(instr)) {
|
||||
if (currentState.isNeverNull(varNum)) {
|
||||
for (T succ : cfg.getExceptionalSuccessors(currentBlock)) {
|
||||
deleted.addEdge(currentBlock, succ);
|
||||
}
|
||||
|
||||
} else if (currentState.isAlwaysNull(varNum)) {
|
||||
for (T succ : cfg.getNormalSuccessors(currentBlock)) {
|
||||
deleted.addEdge(currentBlock, succ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void removeImpossibleSuccessors(SSAInstruction instr, int varNum) {
|
||||
if (isOnlyNullPointerExc(instr)) {
|
||||
if (currentState.isNeverNull(varNum)) {
|
||||
for (T succ : cfg.getExceptionalSuccessors(currentBlock)) {
|
||||
deleted.addEdge(currentBlock, succ);
|
||||
}
|
||||
|
||||
} else if (currentState.isAlwaysNull(varNum)) {
|
||||
for (T succ : cfg.getNormalSuccessors(currentBlock)) {
|
||||
deleted.addEdge(currentBlock, succ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeImpossibleSuccessors(SSAInstruction instr) {
|
||||
if (noExceptions(instr)) {
|
||||
for (T succ : cfg.getExceptionalSuccessors(currentBlock)) {
|
||||
|
@ -278,152 +278,152 @@ public class IntraprocNullPointerAnalysis<T extends ISSABasicBlock> {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayLength(com.ibm.wala.ssa.SSAArrayLengthInstruction)
|
||||
*/
|
||||
public void visitArrayLength(SSAArrayLengthInstruction instruction) {
|
||||
int varNum = instruction.getArrayRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayLength(com.ibm.wala.ssa.SSAArrayLengthInstruction)
|
||||
*/
|
||||
public void visitArrayLength(SSAArrayLengthInstruction instruction) {
|
||||
int varNum = instruction.getArrayRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayLoad(com.ibm.wala.ssa.SSAArrayLoadInstruction)
|
||||
*/
|
||||
public void visitArrayLoad(SSAArrayLoadInstruction instruction) {
|
||||
int varNum = instruction.getArrayRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayLoad(com.ibm.wala.ssa.SSAArrayLoadInstruction)
|
||||
*/
|
||||
public void visitArrayLoad(SSAArrayLoadInstruction instruction) {
|
||||
int varNum = instruction.getArrayRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayStore(com.ibm.wala.ssa.SSAArrayStoreInstruction)
|
||||
*/
|
||||
public void visitArrayStore(SSAArrayStoreInstruction instruction) {
|
||||
int varNum = instruction.getArrayRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayStore(com.ibm.wala.ssa.SSAArrayStoreInstruction)
|
||||
*/
|
||||
public void visitArrayStore(SSAArrayStoreInstruction instruction) {
|
||||
int varNum = instruction.getArrayRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitBinaryOp(com.ibm.wala.ssa.SSABinaryOpInstruction)
|
||||
*/
|
||||
public void visitBinaryOp(SSABinaryOpInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitBinaryOp(com.ibm.wala.ssa.SSABinaryOpInstruction)
|
||||
*/
|
||||
public void visitBinaryOp(SSABinaryOpInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitCheckCast(com.ibm.wala.ssa.SSACheckCastInstruction)
|
||||
*/
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitCheckCast(com.ibm.wala.ssa.SSACheckCastInstruction)
|
||||
*/
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitComparison(com.ibm.wala.ssa.SSAComparisonInstruction)
|
||||
*/
|
||||
public void visitComparison(SSAComparisonInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitComparison(com.ibm.wala.ssa.SSAComparisonInstruction)
|
||||
*/
|
||||
public void visitComparison(SSAComparisonInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitConditionalBranch(com.ibm.wala.ssa.SSAConditionalBranchInstruction)
|
||||
*/
|
||||
public void visitConditionalBranch(SSAConditionalBranchInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitConditionalBranch(com.ibm.wala.ssa.SSAConditionalBranchInstruction)
|
||||
*/
|
||||
public void visitConditionalBranch(SSAConditionalBranchInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitConversion(com.ibm.wala.ssa.SSAConversionInstruction)
|
||||
*/
|
||||
public void visitConversion(SSAConversionInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitConversion(com.ibm.wala.ssa.SSAConversionInstruction)
|
||||
*/
|
||||
public void visitConversion(SSAConversionInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGet(com.ibm.wala.ssa.SSAGetInstruction)
|
||||
*/
|
||||
public void visitGet(SSAGetInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
int varNum = instruction.getRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGet(com.ibm.wala.ssa.SSAGetInstruction)
|
||||
*/
|
||||
public void visitGet(SSAGetInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
int varNum = instruction.getRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGetCaughtException(com.ibm.wala.ssa.SSAGetCaughtExceptionInstruction)
|
||||
*/
|
||||
public void visitGetCaughtException(SSAGetCaughtExceptionInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGetCaughtException(com.ibm.wala.ssa.SSAGetCaughtExceptionInstruction)
|
||||
*/
|
||||
public void visitGetCaughtException(SSAGetCaughtExceptionInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGoto(com.ibm.wala.ssa.SSAGotoInstruction)
|
||||
*/
|
||||
public void visitGoto(SSAGotoInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGoto(com.ibm.wala.ssa.SSAGotoInstruction)
|
||||
*/
|
||||
public void visitGoto(SSAGotoInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitInstanceof(com.ibm.wala.ssa.SSAInstanceofInstruction)
|
||||
*/
|
||||
public void visitInstanceof(SSAInstanceofInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitInstanceof(com.ibm.wala.ssa.SSAInstanceofInstruction)
|
||||
*/
|
||||
public void visitInstanceof(SSAInstanceofInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitInvoke(com.ibm.wala.ssa.SSAInvokeInstruction)
|
||||
*/
|
||||
public void visitInvoke(SSAInvokeInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
int varNum = instruction.getReceiver();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
} else {
|
||||
removeImpossibleSuccessors(instruction);
|
||||
}
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitInvoke(com.ibm.wala.ssa.SSAInvokeInstruction)
|
||||
*/
|
||||
public void visitInvoke(SSAInvokeInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
int varNum = instruction.getReceiver();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
} else {
|
||||
removeImpossibleSuccessors(instruction);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitLoadMetadata(com.ibm.wala.ssa.SSALoadMetadataInstruction)
|
||||
*/
|
||||
public void visitLoadMetadata(SSALoadMetadataInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitLoadMetadata(com.ibm.wala.ssa.SSALoadMetadataInstruction)
|
||||
*/
|
||||
public void visitLoadMetadata(SSALoadMetadataInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitMonitor(com.ibm.wala.ssa.SSAMonitorInstruction)
|
||||
*/
|
||||
public void visitMonitor(SSAMonitorInstruction instruction) {
|
||||
int varNum = instruction.getRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitMonitor(com.ibm.wala.ssa.SSAMonitorInstruction)
|
||||
*/
|
||||
public void visitMonitor(SSAMonitorInstruction instruction) {
|
||||
int varNum = instruction.getRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitNew(com.ibm.wala.ssa.SSANewInstruction)
|
||||
*/
|
||||
public void visitNew(SSANewInstruction instruction) {
|
||||
removeImpossibleSuccessors(instruction);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitNew(com.ibm.wala.ssa.SSANewInstruction)
|
||||
*/
|
||||
public void visitNew(SSANewInstruction instruction) {
|
||||
removeImpossibleSuccessors(instruction);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPhi(com.ibm.wala.ssa.SSAPhiInstruction)
|
||||
*/
|
||||
public void visitPhi(SSAPhiInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPhi(com.ibm.wala.ssa.SSAPhiInstruction)
|
||||
*/
|
||||
public void visitPhi(SSAPhiInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPi(com.ibm.wala.ssa.SSAPiInstruction)
|
||||
*/
|
||||
public void visitPi(SSAPiInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPi(com.ibm.wala.ssa.SSAPiInstruction)
|
||||
*/
|
||||
public void visitPi(SSAPiInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPut(com.ibm.wala.ssa.SSAPutInstruction)
|
||||
*/
|
||||
public void visitPut(SSAPutInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
int varNum = instruction.getRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPut(com.ibm.wala.ssa.SSAPutInstruction)
|
||||
*/
|
||||
public void visitPut(SSAPutInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
int varNum = instruction.getRef();
|
||||
removeImpossibleSuccessors(instruction, varNum);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitReturn(com.ibm.wala.ssa.SSAReturnInstruction)
|
||||
*/
|
||||
public void visitReturn(SSAReturnInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitReturn(com.ibm.wala.ssa.SSAReturnInstruction)
|
||||
*/
|
||||
public void visitReturn(SSAReturnInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitSwitch(com.ibm.wala.ssa.SSASwitchInstruction)
|
||||
*/
|
||||
public void visitSwitch(SSASwitchInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitSwitch(com.ibm.wala.ssa.SSASwitchInstruction)
|
||||
*/
|
||||
public void visitSwitch(SSASwitchInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitThrow(com.ibm.wala.ssa.SSAThrowInstruction)
|
||||
*/
|
||||
public void visitThrow(SSAThrowInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitThrow(com.ibm.wala.ssa.SSAThrowInstruction)
|
||||
*/
|
||||
public void visitThrow(SSAThrowInstruction instruction) {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitUnaryOp(com.ibm.wala.ssa.SSAUnaryOpInstruction)
|
||||
*/
|
||||
public void visitUnaryOp(SSAUnaryOpInstruction instruction) {}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitUnaryOp(com.ibm.wala.ssa.SSAUnaryOpInstruction)
|
||||
*/
|
||||
public void visitUnaryOp(SSAUnaryOpInstruction instruction) {}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
|
|||
*/
|
||||
public abstract class MethodState {
|
||||
|
||||
public abstract boolean throwsException(SSAAbstractInvokeInstruction node);
|
||||
|
||||
public static final MethodState DEFAULT = new MethodState() {
|
||||
public abstract boolean throwsException(SSAAbstractInvokeInstruction node);
|
||||
|
||||
public static final MethodState DEFAULT = new MethodState() {
|
||||
|
||||
@Override
|
||||
public boolean throwsException(SSAAbstractInvokeInstruction node) {
|
||||
|
|
|
@ -12,27 +12,27 @@ import com.ibm.wala.util.graph.impl.SparseNumberedGraph;
|
|||
*/
|
||||
public class MutableCFG<X, T extends IBasicBlock<X>> extends SparseNumberedGraph<T> {
|
||||
|
||||
private MutableCFG() {
|
||||
}
|
||||
|
||||
public static <I, T extends IBasicBlock<I>> MutableCFG<I, T> copyFrom(ControlFlowGraph<I, T> cfg) {
|
||||
MutableCFG<I, T> mutable = new MutableCFG<I, T>();
|
||||
|
||||
for (T node : cfg) {
|
||||
mutable.addNode(node);
|
||||
}
|
||||
|
||||
for (T node : cfg) {
|
||||
for (T succ : cfg.getNormalSuccessors(node)) {
|
||||
mutable.addEdge(node, succ);
|
||||
}
|
||||
private MutableCFG() {
|
||||
}
|
||||
|
||||
public static <I, T extends IBasicBlock<I>> MutableCFG<I, T> copyFrom(ControlFlowGraph<I, T> cfg) {
|
||||
MutableCFG<I, T> mutable = new MutableCFG<I, T>();
|
||||
|
||||
for (T node : cfg) {
|
||||
mutable.addNode(node);
|
||||
}
|
||||
|
||||
for (T node : cfg) {
|
||||
for (T succ : cfg.getNormalSuccessors(node)) {
|
||||
mutable.addEdge(node, succ);
|
||||
}
|
||||
|
||||
for (T succ : cfg.getExceptionalSuccessors(node)) {
|
||||
mutable.addEdge(node, succ);
|
||||
}
|
||||
}
|
||||
|
||||
return mutable;
|
||||
}
|
||||
|
||||
for (T succ : cfg.getExceptionalSuccessors(node)) {
|
||||
mutable.addEdge(node, succ);
|
||||
}
|
||||
}
|
||||
|
||||
return mutable;
|
||||
}
|
||||
|
||||
}
|
|
@ -13,24 +13,24 @@ import com.ibm.wala.util.graph.Graph;
|
|||
*/
|
||||
public class NegativeGraphFilter<T extends IBasicBlock<?>> implements EdgeFilter<T> {
|
||||
|
||||
private final Graph<T> deleted;
|
||||
|
||||
public NegativeGraphFilter(Graph<T> deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.cfg.EdgeFilter#hasExceptionalEdge(com.ibm.wala.cfg.IBasicBlock, com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public boolean hasExceptionalEdge(T src, T dst) {
|
||||
return !deleted.hasEdge(src, dst);
|
||||
}
|
||||
private final Graph<T> deleted;
|
||||
|
||||
public NegativeGraphFilter(Graph<T> deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.cfg.EdgeFilter#hasExceptionalEdge(com.ibm.wala.cfg.IBasicBlock, com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public boolean hasExceptionalEdge(T src, T dst) {
|
||||
return !deleted.hasEdge(src, dst);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.cfg.EdgeFilter#hasNormalEdge(com.ibm.wala.cfg.IBasicBlock, com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public boolean hasNormalEdge(T src, T dst) {
|
||||
return !deleted.hasEdge(src, dst);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ipa.cfg.EdgeFilter#hasNormalEdge(com.ibm.wala.cfg.IBasicBlock, com.ibm.wala.cfg.IBasicBlock)
|
||||
*/
|
||||
public boolean hasNormalEdge(T src, T dst) {
|
||||
return !deleted.hasEdge(src, dst);
|
||||
}
|
||||
|
||||
}
|
|
@ -20,42 +20,42 @@ import com.ibm.wala.util.intset.IntPair;
|
|||
*/
|
||||
class NullPointerFrameWork<T extends ISSABasicBlock> implements IKilldallFramework<T, NullPointerState> {
|
||||
|
||||
private final Graph<T> flow;
|
||||
private final NullPointerTransferFunctionProvider<T> transferFunct;
|
||||
|
||||
NullPointerFrameWork(ControlFlowGraph<SSAInstruction, T> cfg, IR ir) {
|
||||
final IBinaryNaturalRelation backEdges = Acyclic.computeBackEdges(cfg, cfg.entry());
|
||||
boolean hasBackEdge = backEdges.iterator().hasNext();
|
||||
if (hasBackEdge) {
|
||||
MutableCFG<SSAInstruction, T> cfg2 = MutableCFG.copyFrom(cfg);
|
||||
|
||||
for (IntPair edge : backEdges) {
|
||||
T from = cfg2.getNode(edge.getX());
|
||||
T to = cfg2.getNode(edge.getY());
|
||||
cfg2.removeEdge(from, to);
|
||||
cfg2.addEdge(from, cfg.exit());
|
||||
}
|
||||
|
||||
this.flow = cfg2;
|
||||
} else {
|
||||
this.flow = cfg;
|
||||
}
|
||||
private final Graph<T> flow;
|
||||
private final NullPointerTransferFunctionProvider<T> transferFunct;
|
||||
|
||||
NullPointerFrameWork(ControlFlowGraph<SSAInstruction, T> cfg, IR ir) {
|
||||
final IBinaryNaturalRelation backEdges = Acyclic.computeBackEdges(cfg, cfg.entry());
|
||||
boolean hasBackEdge = backEdges.iterator().hasNext();
|
||||
if (hasBackEdge) {
|
||||
MutableCFG<SSAInstruction, T> cfg2 = MutableCFG.copyFrom(cfg);
|
||||
|
||||
for (IntPair edge : backEdges) {
|
||||
T from = cfg2.getNode(edge.getX());
|
||||
T to = cfg2.getNode(edge.getY());
|
||||
cfg2.removeEdge(from, to);
|
||||
cfg2.addEdge(from, cfg.exit());
|
||||
}
|
||||
|
||||
this.flow = cfg2;
|
||||
} else {
|
||||
this.flow = cfg;
|
||||
}
|
||||
|
||||
this.transferFunct = new NullPointerTransferFunctionProvider<T>(cfg, ir);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.IKilldallFramework#getFlowGraph()
|
||||
*/
|
||||
public Graph<T> getFlowGraph() {
|
||||
return flow;
|
||||
}
|
||||
this.transferFunct = new NullPointerTransferFunctionProvider<T>(cfg, ir);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.IKilldallFramework#getFlowGraph()
|
||||
*/
|
||||
public Graph<T> getFlowGraph() {
|
||||
return flow;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.IKilldallFramework#getTransferFunctionProvider()
|
||||
*/
|
||||
public NullPointerTransferFunctionProvider<T> getTransferFunctionProvider() {
|
||||
return transferFunct;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.IKilldallFramework#getTransferFunctionProvider()
|
||||
*/
|
||||
public NullPointerTransferFunctionProvider<T> getTransferFunctionProvider() {
|
||||
return transferFunct;
|
||||
}
|
||||
|
||||
}
|
|
@ -13,108 +13,108 @@ import com.ibm.wala.ssa.SymbolTable;
|
|||
*
|
||||
*/
|
||||
public class NullPointerState extends AbstractVariable<NullPointerState> {
|
||||
|
||||
/*
|
||||
* Inital state is UNKNOWN.
|
||||
* Lattice: UNKNOWN < { NULL, NOT_NULL } < BOTH
|
||||
*/
|
||||
public enum State { UNKNOWN, BOTH, NULL, NOT_NULL };
|
||||
|
||||
// maps ssa variable number -> State
|
||||
private final State[] vars;
|
||||
|
||||
NullPointerState(int maxVarNum, SymbolTable symbolTable, ParameterState parameterState) {
|
||||
this.vars = new State[maxVarNum + 1];
|
||||
|
||||
// Initialize the states
|
||||
for (int i = 0; i < vars.length; i++) {
|
||||
if (symbolTable.isConstant(i)){
|
||||
if (symbolTable.isNullConstant(i)){
|
||||
vars[i] = State.NULL;
|
||||
} else {
|
||||
vars[i] = State.NOT_NULL;
|
||||
}
|
||||
} else {
|
||||
vars[i] = State.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// Add what we know about the parameters (if we know anything about them).
|
||||
// They are the first vars by convention.
|
||||
if (parameterState != null) {
|
||||
for (int i = 0; i < parameterState.getStates().size(); i++){
|
||||
assert parameterState.getState(i) != null;
|
||||
vars[i + 1] = parameterState.getState(i);
|
||||
assert vars[i + 1] != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Inital state is UNKNOWN.
|
||||
* Lattice: UNKNOWN < { NULL, NOT_NULL } < BOTH
|
||||
*/
|
||||
public enum State { UNKNOWN, BOTH, NULL, NOT_NULL };
|
||||
|
||||
// maps ssa variable number -> State
|
||||
private final State[] vars;
|
||||
|
||||
NullPointerState(int maxVarNum, SymbolTable symbolTable, ParameterState parameterState) {
|
||||
this.vars = new State[maxVarNum + 1];
|
||||
|
||||
// Initialize the states
|
||||
for (int i = 0; i < vars.length; i++) {
|
||||
if (symbolTable.isConstant(i)){
|
||||
if (symbolTable.isNullConstant(i)){
|
||||
vars[i] = State.NULL;
|
||||
} else {
|
||||
vars[i] = State.NOT_NULL;
|
||||
}
|
||||
} else {
|
||||
vars[i] = State.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// Add what we know about the parameters (if we know anything about them).
|
||||
// They are the first vars by convention.
|
||||
if (parameterState != null) {
|
||||
for (int i = 0; i < parameterState.getStates().size(); i++){
|
||||
assert parameterState.getState(i) != null;
|
||||
vars[i + 1] = parameterState.getState(i);
|
||||
assert vars[i + 1] != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AbstractMeetOperator<NullPointerState> meetOperator() {
|
||||
return StateMeet.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is not distributive, therefore we cannot use the kildall framework.
|
||||
* <pre>
|
||||
* v3 = phi v1, v2
|
||||
* ^ := Meet-operator
|
||||
* f := phiValueMeetFunction(3, {1, 2}) = v1,v2,v3 -> v1,v2,[v1 ^ v2]
|
||||
*
|
||||
* f(1,?,?) ^ f(?,1,?) = 1,?,? ^ ?,1,? = 1,1,?
|
||||
*
|
||||
* f(1,?,? ^ ?,1,?) = f(1,1,?) = 1,1,1
|
||||
*
|
||||
* => f(1,?,? ^ ?,1,?) != f(1,?,?) ^ f(?,1,?)
|
||||
* </pre>
|
||||
*/
|
||||
static UnaryOperator<NullPointerState> phiValueMeetFunction(int varNum, int[] fromVars) {
|
||||
return new PhiValueMeet(varNum, fromVars);
|
||||
}
|
||||
|
||||
static UnaryOperator<NullPointerState> nullifyFunction(int varNum) {
|
||||
return new NullifyFunction(varNum);
|
||||
}
|
||||
|
||||
static UnaryOperator<NullPointerState> denullifyFunction(int varNum) {
|
||||
return new DenullifyFunction(varNum);
|
||||
}
|
||||
|
||||
static UnaryOperator<NullPointerState> identityFunction() {
|
||||
return IndentityFunction.INSTANCE;
|
||||
}
|
||||
|
||||
boolean isNeverNull(int varNum) {
|
||||
assert varNum > 0 && varNum < vars.length;
|
||||
|
||||
return vars[varNum] == State.NOT_NULL;
|
||||
}
|
||||
|
||||
boolean isAlwaysNull(int varNum) {
|
||||
assert varNum > 0 && varNum < vars.length;
|
||||
|
||||
return vars[varNum] == State.NULL;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixpoint.IVariable#copyState(com.ibm.wala.fixpoint.IVariable)
|
||||
*/
|
||||
public void copyState(NullPointerState v) {
|
||||
assert v.vars.length == vars.length;
|
||||
|
||||
for (int i = 0; i < v.vars.length; i++) {
|
||||
vars[i] = v.vars[i];
|
||||
}
|
||||
}
|
||||
static AbstractMeetOperator<NullPointerState> meetOperator() {
|
||||
return StateMeet.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is not distributive, therefore we cannot use the kildall framework.
|
||||
* <pre>
|
||||
* v3 = phi v1, v2
|
||||
* ^ := Meet-operator
|
||||
* f := phiValueMeetFunction(3, {1, 2}) = v1,v2,v3 -> v1,v2,[v1 ^ v2]
|
||||
*
|
||||
* f(1,?,?) ^ f(?,1,?) = 1,?,? ^ ?,1,? = 1,1,?
|
||||
*
|
||||
* f(1,?,? ^ ?,1,?) = f(1,1,?) = 1,1,1
|
||||
*
|
||||
* => f(1,?,? ^ ?,1,?) != f(1,?,?) ^ f(?,1,?)
|
||||
* </pre>
|
||||
*/
|
||||
static UnaryOperator<NullPointerState> phiValueMeetFunction(int varNum, int[] fromVars) {
|
||||
return new PhiValueMeet(varNum, fromVars);
|
||||
}
|
||||
|
||||
static UnaryOperator<NullPointerState> nullifyFunction(int varNum) {
|
||||
return new NullifyFunction(varNum);
|
||||
}
|
||||
|
||||
static UnaryOperator<NullPointerState> denullifyFunction(int varNum) {
|
||||
return new DenullifyFunction(varNum);
|
||||
}
|
||||
|
||||
static UnaryOperator<NullPointerState> identityFunction() {
|
||||
return IndentityFunction.INSTANCE;
|
||||
}
|
||||
|
||||
boolean isNeverNull(int varNum) {
|
||||
assert varNum > 0 && varNum < vars.length;
|
||||
|
||||
return vars[varNum] == State.NOT_NULL;
|
||||
}
|
||||
|
||||
boolean isAlwaysNull(int varNum) {
|
||||
assert varNum > 0 && varNum < vars.length;
|
||||
|
||||
return vars[varNum] == State.NULL;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixpoint.IVariable#copyState(com.ibm.wala.fixpoint.IVariable)
|
||||
*/
|
||||
public void copyState(NullPointerState v) {
|
||||
assert v.vars.length == vars.length;
|
||||
|
||||
for (int i = 0; i < v.vars.length; i++) {
|
||||
vars[i] = v.vars[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the meet operator for the EdgeState variables.
|
||||
* <pre>
|
||||
* ? == unknown, 1 == not null, 0 == null, * == both
|
||||
*
|
||||
* meet | ? | 0 | 1 | * | <- rhs
|
||||
* -----|---|---|---|---|
|
||||
* ? | ? | 0 | 1 | * |
|
||||
/**
|
||||
* This is the meet operator for the NullPointerState variables.
|
||||
* <pre>
|
||||
* ? == unknown, 1 == not null, 0 == null, * == both
|
||||
*
|
||||
* meet | ? | 0 | 1 | * | <- rhs
|
||||
* -----|---|---|---|---|
|
||||
* ? | ? | 0 | 1 | * |
|
||||
* -----|---|---|---|---|
|
||||
* 0 | 0 | 0 | * | * |
|
||||
* -----|---|---|---|---|
|
||||
|
@ -125,38 +125,38 @@ public class NullPointerState extends AbstractVariable<NullPointerState> {
|
|||
* ^
|
||||
* |
|
||||
* lhs
|
||||
* </pre>
|
||||
*/
|
||||
boolean meet(final int varNum, final State rhs) {
|
||||
* </pre>
|
||||
*/
|
||||
boolean meet(final int varNum, final State rhs) {
|
||||
final State lhs = vars[varNum];
|
||||
|
||||
if (lhs != State.BOTH && rhs != lhs && rhs != State.UNKNOWN) {
|
||||
if (lhs == State.UNKNOWN) {
|
||||
if (lhs != State.BOTH && rhs != lhs && rhs != State.UNKNOWN) {
|
||||
if (lhs == State.UNKNOWN) {
|
||||
vars[varNum] = rhs;
|
||||
return true;
|
||||
} else {
|
||||
vars[varNum] = State.BOTH;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vars[varNum] = State.BOTH;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean meet(NullPointerState other) {
|
||||
assert other.vars.length == vars.length;
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
for (int i = 0; i < vars.length; i++) {
|
||||
changed |= meet(i, other.vars[i]);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a intersect operator for the EdgeState variables. It is used by the
|
||||
boolean meet(NullPointerState other) {
|
||||
assert other.vars.length == vars.length;
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
for (int i = 0; i < vars.length; i++) {
|
||||
changed |= meet(i, other.vars[i]);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a intersect operator for the NullPointerState variables. It is used by the
|
||||
* phi values.
|
||||
* <pre>
|
||||
* ? == unknown, 1 == not null, 0 == null, * == both
|
||||
|
@ -192,352 +192,352 @@ public class NullPointerState extends AbstractVariable<NullPointerState> {
|
|||
}
|
||||
}
|
||||
|
||||
boolean nullify(int varNum) {
|
||||
if (vars[varNum] != State.NULL) {
|
||||
vars[varNum] = State.NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean denullify(int varNum) {
|
||||
boolean nullify(int varNum) {
|
||||
if (vars[varNum] != State.NULL) {
|
||||
vars[varNum] = State.NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean denullify(int varNum) {
|
||||
if (vars[varNum] != State.NOT_NULL) {
|
||||
vars[varNum] = State.NOT_NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof NullPointerState) {
|
||||
NullPointerState other = (NullPointerState) obj;
|
||||
assert vars.length == other.vars.length;
|
||||
|
||||
for (int i = 0; i < vars.length; i++) {
|
||||
if (vars[i] != other.vars[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public State getState(int ssaVarNum){
|
||||
return vars[ssaVarNum];
|
||||
}
|
||||
|
||||
@Override
|
||||
if (obj instanceof NullPointerState) {
|
||||
NullPointerState other = (NullPointerState) obj;
|
||||
assert vars.length == other.vars.length;
|
||||
|
||||
for (int i = 0; i < vars.length; i++) {
|
||||
if (vars[i] != other.vars[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public State getState(int ssaVarNum){
|
||||
return vars[ssaVarNum];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer("<");
|
||||
for (int i = 0; i < vars.length; i++) {
|
||||
switch (vars[i]) {
|
||||
case BOTH:
|
||||
buf.append('*');
|
||||
break;
|
||||
case NOT_NULL:
|
||||
buf.append('1');
|
||||
break;
|
||||
case NULL:
|
||||
buf.append('0');
|
||||
break;
|
||||
case UNKNOWN:
|
||||
buf.append('?');
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
buf.append('>');
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private static class StateMeet extends AbstractMeetOperator<NullPointerState> {
|
||||
StringBuffer buf = new StringBuffer("<");
|
||||
for (int i = 0; i < vars.length; i++) {
|
||||
switch (vars[i]) {
|
||||
case BOTH:
|
||||
buf.append('*');
|
||||
break;
|
||||
case NOT_NULL:
|
||||
buf.append('1');
|
||||
break;
|
||||
case NULL:
|
||||
buf.append('0');
|
||||
break;
|
||||
case UNKNOWN:
|
||||
buf.append('?');
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
buf.append('>');
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private static class StateMeet extends AbstractMeetOperator<NullPointerState> {
|
||||
|
||||
private final static StateMeet INSTANCE = new StateMeet();
|
||||
|
||||
private StateMeet() {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof StateMeet;
|
||||
}
|
||||
private final static StateMeet INSTANCE = new StateMeet();
|
||||
|
||||
private StateMeet() {}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof StateMeet;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#evaluate(com.ibm.wala.fixpoint.IVariable, com.ibm.wala.fixpoint.IVariable[])
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public byte evaluate(NullPointerState lhs, NullPointerState[] rhs) {
|
||||
boolean changed = false;
|
||||
|
||||
// meet rhs first
|
||||
for (NullPointerState state : rhs) {
|
||||
changed |= lhs.meet(state);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#evaluate(com.ibm.wala.fixpoint.IVariable, com.ibm.wala.fixpoint.IVariable[])
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public byte evaluate(NullPointerState lhs, NullPointerState[] rhs) {
|
||||
boolean changed = false;
|
||||
|
||||
// meet rhs first
|
||||
for (NullPointerState state : rhs) {
|
||||
changed |= lhs.meet(state);
|
||||
}
|
||||
|
||||
return (changed ? FixedPointConstants.CHANGED : FixedPointConstants.NOT_CHANGED);
|
||||
}
|
||||
return (changed ? FixedPointConstants.CHANGED : FixedPointConstants.NOT_CHANGED);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 4711;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 4711;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EdgeStateMeet";
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NullPointerStateMeet";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class PhiValueMeet extends UnaryOperator<NullPointerState> {
|
||||
}
|
||||
|
||||
private static class PhiValueMeet extends UnaryOperator<NullPointerState> {
|
||||
|
||||
private final int varNum;
|
||||
private final int[] fromVars;
|
||||
|
||||
/**
|
||||
* Creates an operator that merges the states of the given variables
|
||||
* fromVars into the state of the phi varaiable varNum
|
||||
* @param varNum Variable number of a phi value
|
||||
* @param fromVars Array of variable numbers the phi value refers to.
|
||||
*/
|
||||
private PhiValueMeet(int varNum, int[] fromVars) {
|
||||
this.varNum = varNum;
|
||||
this.fromVars = fromVars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte evaluate(NullPointerState lhs, NullPointerState rhs) {
|
||||
byte state = FixedPointConstants.NOT_CHANGED;
|
||||
|
||||
for (int from : fromVars) {
|
||||
if (lhs.intersect(varNum, rhs.vars[from])) {
|
||||
state = FixedPointConstants.CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
private final int varNum;
|
||||
private final int[] fromVars;
|
||||
|
||||
/**
|
||||
* Creates an operator that merges the states of the given variables
|
||||
* fromVars into the state of the phi varaiable varNum
|
||||
* @param varNum Variable number of a phi value
|
||||
* @param fromVars Array of variable numbers the phi value refers to.
|
||||
*/
|
||||
private PhiValueMeet(int varNum, int[] fromVars) {
|
||||
this.varNum = varNum;
|
||||
this.fromVars = fromVars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte evaluate(NullPointerState lhs, NullPointerState rhs) {
|
||||
byte state = FixedPointConstants.NOT_CHANGED;
|
||||
|
||||
for (int from : fromVars) {
|
||||
if (lhs.intersect(varNum, rhs.vars[from])) {
|
||||
state = FixedPointConstants.CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (o instanceof PhiValueMeet) {
|
||||
PhiValueMeet other = (PhiValueMeet) o;
|
||||
if (varNum == other.varNum && fromVars.length == other.fromVars.length) {
|
||||
for (int i = 0; i < fromVars.length; i++) {
|
||||
if (fromVars[i] != other.fromVars[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (o instanceof PhiValueMeet) {
|
||||
PhiValueMeet other = (PhiValueMeet) o;
|
||||
if (varNum == other.varNum && fromVars.length == other.fromVars.length) {
|
||||
for (int i = 0; i < fromVars.length; i++) {
|
||||
if (fromVars[i] != other.fromVars[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 11000 + varNum;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 11000 + varNum;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer str = new StringBuffer("Meet(" + varNum + ", [");
|
||||
|
||||
for (int i = 0; i < fromVars.length; i++) {
|
||||
str.append(fromVars[i]);
|
||||
str.append(i == fromVars.length - 1 ? "" : ",");
|
||||
}
|
||||
|
||||
str.append("])");
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer str = new StringBuffer("Meet(" + varNum + ", [");
|
||||
|
||||
for (int i = 0; i < fromVars.length; i++) {
|
||||
str.append(fromVars[i]);
|
||||
str.append(i == fromVars.length - 1 ? "" : ",");
|
||||
}
|
||||
|
||||
str.append("])");
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class NullifyFunction extends UnaryOperator<NullPointerState> {
|
||||
}
|
||||
|
||||
private static class NullifyFunction extends UnaryOperator<NullPointerState> {
|
||||
|
||||
private final int varNum;
|
||||
|
||||
private NullifyFunction(int varNum) {
|
||||
this.varNum = varNum;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.UnaryOperator#evaluate(com.ibm.wala.fixpoint.IVariable, com.ibm.wala.fixpoint.IVariable)
|
||||
*/
|
||||
@Override
|
||||
public byte evaluate(NullPointerState lhs, NullPointerState rhs) {
|
||||
byte state = FixedPointConstants.NOT_CHANGED;
|
||||
|
||||
if (!lhs.equals(rhs)) {
|
||||
lhs.copyState(rhs);
|
||||
state = FixedPointConstants.CHANGED;
|
||||
}
|
||||
|
||||
if (lhs.nullify(varNum)) {
|
||||
state = FixedPointConstants.CHANGED;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
private final int varNum;
|
||||
|
||||
private NullifyFunction(int varNum) {
|
||||
this.varNum = varNum;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.UnaryOperator#evaluate(com.ibm.wala.fixpoint.IVariable, com.ibm.wala.fixpoint.IVariable)
|
||||
*/
|
||||
@Override
|
||||
public byte evaluate(NullPointerState lhs, NullPointerState rhs) {
|
||||
byte state = FixedPointConstants.NOT_CHANGED;
|
||||
|
||||
if (!lhs.equals(rhs)) {
|
||||
lhs.copyState(rhs);
|
||||
state = FixedPointConstants.CHANGED;
|
||||
}
|
||||
|
||||
if (lhs.nullify(varNum)) {
|
||||
state = FixedPointConstants.CHANGED;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof NullifyFunction && ((NullifyFunction) o).varNum == varNum;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof NullifyFunction && ((NullifyFunction) o).varNum == varNum;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 47000 + varNum;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 47000 + varNum;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Nullify(" + varNum + ")";
|
||||
}
|
||||
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Nullify(" + varNum + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DenullifyFunction extends UnaryOperator<NullPointerState> {
|
||||
private static class DenullifyFunction extends UnaryOperator<NullPointerState> {
|
||||
|
||||
private final int varNum;
|
||||
|
||||
private DenullifyFunction(int varNum) {
|
||||
assert varNum >= 0;
|
||||
this.varNum = varNum;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.UnaryOperator#evaluate(com.ibm.wala.fixpoint.IVariable, com.ibm.wala.fixpoint.IVariable)
|
||||
*/
|
||||
@Override
|
||||
public byte evaluate(NullPointerState lhs, NullPointerState rhs) {
|
||||
byte state = FixedPointConstants.NOT_CHANGED;
|
||||
|
||||
if (!lhs.equals(rhs)) {
|
||||
lhs.copyState(rhs);
|
||||
state = FixedPointConstants.CHANGED;
|
||||
}
|
||||
|
||||
if (lhs.denullify(varNum)) {
|
||||
state = FixedPointConstants.CHANGED;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
private final int varNum;
|
||||
|
||||
private DenullifyFunction(int varNum) {
|
||||
assert varNum >= 0;
|
||||
this.varNum = varNum;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.UnaryOperator#evaluate(com.ibm.wala.fixpoint.IVariable, com.ibm.wala.fixpoint.IVariable)
|
||||
*/
|
||||
@Override
|
||||
public byte evaluate(NullPointerState lhs, NullPointerState rhs) {
|
||||
byte state = FixedPointConstants.NOT_CHANGED;
|
||||
|
||||
if (!lhs.equals(rhs)) {
|
||||
lhs.copyState(rhs);
|
||||
state = FixedPointConstants.CHANGED;
|
||||
}
|
||||
|
||||
if (lhs.denullify(varNum)) {
|
||||
state = FixedPointConstants.CHANGED;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof DenullifyFunction && ((DenullifyFunction) o).varNum == varNum;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof DenullifyFunction && ((DenullifyFunction) o).varNum == varNum;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return -47000 - varNum;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return -47000 - varNum;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Denullify(" + varNum + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class IndentityFunction extends UnaryOperator<NullPointerState> {
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Denullify(" + varNum + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class IndentityFunction extends UnaryOperator<NullPointerState> {
|
||||
|
||||
private static final IndentityFunction INSTANCE = new IndentityFunction();
|
||||
|
||||
private IndentityFunction() {
|
||||
}
|
||||
private static final IndentityFunction INSTANCE = new IndentityFunction();
|
||||
|
||||
private IndentityFunction() {
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.UnaryOperator#evaluate(com.ibm.wala.fixpoint.IVariable, com.ibm.wala.fixpoint.IVariable)
|
||||
*/
|
||||
@Override
|
||||
public byte evaluate(NullPointerState lhs, NullPointerState rhs) {
|
||||
if (lhs.equals(rhs)) {
|
||||
return FixedPointConstants.NOT_CHANGED;
|
||||
} else {
|
||||
lhs.copyState(rhs);
|
||||
return FixedPointConstants.CHANGED;
|
||||
}
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.UnaryOperator#evaluate(com.ibm.wala.fixpoint.IVariable, com.ibm.wala.fixpoint.IVariable)
|
||||
*/
|
||||
@Override
|
||||
public byte evaluate(NullPointerState lhs, NullPointerState rhs) {
|
||||
if (lhs.equals(rhs)) {
|
||||
return FixedPointConstants.NOT_CHANGED;
|
||||
} else {
|
||||
lhs.copyState(rhs);
|
||||
return FixedPointConstants.CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof IndentityFunction;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof IndentityFunction;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 8911;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 8911;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Id";
|
||||
}
|
||||
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.fixedpoint.impl.AbstractOperator#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Id";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -43,398 +43,398 @@ import com.ibm.wala.ssa.analysis.IExplodedBasicBlock;
|
|||
*/
|
||||
class NullPointerTransferFunctionProvider<T extends ISSABasicBlock> implements ITransferFunctionProvider<T, NullPointerState> {
|
||||
|
||||
private final AbstractMeetOperator<NullPointerState> meet = NullPointerState.meetOperator();
|
||||
private final TransferFunctionSSAVisitor visitor;
|
||||
private final ControlFlowGraph<SSAInstruction, T> cfg;
|
||||
|
||||
|
||||
NullPointerTransferFunctionProvider(ControlFlowGraph<SSAInstruction, T> cfg, IR ir) {
|
||||
this.visitor = new TransferFunctionSSAVisitor(ir);
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
static <T extends ISSABasicBlock> SSAInstruction getRelevantInstruction(T block) {
|
||||
SSAInstruction instr = null;
|
||||
if (block.getLastInstructionIndex() >= 0) {
|
||||
instr = block.getLastInstruction();
|
||||
}
|
||||
|
||||
if (instr == null && block.isCatchBlock()) {
|
||||
if (block instanceof IExplodedBasicBlock) {
|
||||
instr = ((IExplodedBasicBlock) block).getCatchInstruction();
|
||||
} else if (block instanceof SSACFG.ExceptionHandlerBasicBlock) {
|
||||
instr = ((SSACFG.ExceptionHandlerBasicBlock) block).getCatchInstruction();
|
||||
} else {
|
||||
throw new IllegalStateException("Unable to get catch instruction from unknown ISSABasicBlock implementation.");
|
||||
}
|
||||
}
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getEdgeTransferFunction(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public UnaryOperator<NullPointerState> getEdgeTransferFunction(T src, T dst) {
|
||||
SSAInstruction instr = getRelevantInstruction(src);
|
||||
|
||||
if (instr != null && cfg.hasEdge(src, dst)) {
|
||||
instr.visit(visitor);
|
||||
if (visitor.noIdentity) {
|
||||
// do stuff
|
||||
if (Util.endsWithConditionalBranch(cfg, src)) {
|
||||
if (Util.getTakenSuccessor(cfg, src) == dst) {
|
||||
// condition is true -> take function 1
|
||||
return visitor.transfer1;
|
||||
} else if (Util.getNotTakenSuccessor(cfg, src) == dst) {
|
||||
// condition is true -> take function 2
|
||||
return visitor.transfer2;
|
||||
} else {
|
||||
throw new IllegalStateException("Successor of if clause is neither true nor false case.");
|
||||
}
|
||||
} else {
|
||||
if (cfg.getNormalSuccessors(src).contains(dst)) {
|
||||
// normal case without exception -> take function 1
|
||||
return visitor.transfer1;
|
||||
} else if (cfg.getExceptionalSuccessors(src).contains(dst)) {
|
||||
// exception has been raised -> take function 2
|
||||
return visitor.transfer2;
|
||||
} else {
|
||||
throw new IllegalStateException("Successor not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NullPointerState.identityFunction();
|
||||
}
|
||||
private final AbstractMeetOperator<NullPointerState> meet = NullPointerState.meetOperator();
|
||||
private final TransferFunctionSSAVisitor visitor;
|
||||
private final ControlFlowGraph<SSAInstruction, T> cfg;
|
||||
|
||||
|
||||
NullPointerTransferFunctionProvider(ControlFlowGraph<SSAInstruction, T> cfg, IR ir) {
|
||||
this.visitor = new TransferFunctionSSAVisitor(ir);
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
static <T extends ISSABasicBlock> SSAInstruction getRelevantInstruction(T block) {
|
||||
SSAInstruction instr = null;
|
||||
if (block.getLastInstructionIndex() >= 0) {
|
||||
instr = block.getLastInstruction();
|
||||
}
|
||||
|
||||
if (instr == null && block.isCatchBlock()) {
|
||||
if (block instanceof IExplodedBasicBlock) {
|
||||
instr = ((IExplodedBasicBlock) block).getCatchInstruction();
|
||||
} else if (block instanceof SSACFG.ExceptionHandlerBasicBlock) {
|
||||
instr = ((SSACFG.ExceptionHandlerBasicBlock) block).getCatchInstruction();
|
||||
} else {
|
||||
throw new IllegalStateException("Unable to get catch instruction from unknown ISSABasicBlock implementation.");
|
||||
}
|
||||
}
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getEdgeTransferFunction(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public UnaryOperator<NullPointerState> getEdgeTransferFunction(T src, T dst) {
|
||||
SSAInstruction instr = getRelevantInstruction(src);
|
||||
|
||||
if (instr != null && cfg.hasEdge(src, dst)) {
|
||||
instr.visit(visitor);
|
||||
if (visitor.noIdentity) {
|
||||
// do stuff
|
||||
if (Util.endsWithConditionalBranch(cfg, src)) {
|
||||
if (Util.getTakenSuccessor(cfg, src) == dst) {
|
||||
// condition is true -> take function 1
|
||||
return visitor.transfer1;
|
||||
} else if (Util.getNotTakenSuccessor(cfg, src) == dst) {
|
||||
// condition is true -> take function 2
|
||||
return visitor.transfer2;
|
||||
} else {
|
||||
throw new IllegalStateException("Successor of if clause is neither true nor false case.");
|
||||
}
|
||||
} else {
|
||||
if (cfg.getNormalSuccessors(src).contains(dst)) {
|
||||
// normal case without exception -> take function 1
|
||||
return visitor.transfer1;
|
||||
} else if (cfg.getExceptionalSuccessors(src).contains(dst)) {
|
||||
// exception has been raised -> take function 2
|
||||
return visitor.transfer2;
|
||||
} else {
|
||||
throw new IllegalStateException("Successor not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getMeetOperator()
|
||||
*/
|
||||
public AbstractMeetOperator<NullPointerState> getMeetOperator() {
|
||||
return meet;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getMeetOperator()
|
||||
*/
|
||||
public AbstractMeetOperator<NullPointerState> getMeetOperator() {
|
||||
return meet;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getNodeTransferFunction(java.lang.Object)
|
||||
*/
|
||||
public UnaryOperator<NullPointerState> getNodeTransferFunction(T node) {
|
||||
throw new UnsupportedOperationException("We do not have such a thing dude!");
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getNodeTransferFunction(java.lang.Object)
|
||||
*/
|
||||
public UnaryOperator<NullPointerState> getNodeTransferFunction(T node) {
|
||||
throw new UnsupportedOperationException("We do not have such a thing dude!");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#hasEdgeTransferFunctions()
|
||||
*/
|
||||
public boolean hasEdgeTransferFunctions() {
|
||||
return true;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#hasEdgeTransferFunctions()
|
||||
*/
|
||||
public boolean hasEdgeTransferFunctions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#hasNodeTransferFunctions()
|
||||
*/
|
||||
public boolean hasNodeTransferFunctions() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class TransferFunctionSSAVisitor implements IVisitor {
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#hasNodeTransferFunctions()
|
||||
*/
|
||||
public boolean hasNodeTransferFunctions() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class TransferFunctionSSAVisitor implements IVisitor {
|
||||
|
||||
private final SymbolTable sym;
|
||||
private final SymbolTable sym;
|
||||
|
||||
// used for true case of if clause and non-exception path
|
||||
private UnaryOperator<NullPointerState> transfer1 = NullPointerState.identityFunction();
|
||||
|
||||
// used for false case of if clause and exceptional path
|
||||
private UnaryOperator<NullPointerState> transfer2 = NullPointerState.identityFunction();
|
||||
|
||||
// true if sth will change. false => just use identity transfer function.
|
||||
private boolean noIdentity = false;
|
||||
|
||||
private TransferFunctionSSAVisitor(IR ir) {
|
||||
this.sym = ir.getSymbolTable();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayLength(com.ibm.wala.ssa.SSAArrayLengthInstruction)
|
||||
*/
|
||||
public void visitArrayLength(SSAArrayLengthInstruction instruction) {
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getArrayRef());
|
||||
transfer2 = NullPointerState.nullifyFunction(instruction.getArrayRef());
|
||||
}
|
||||
// used for true case of if clause and non-exception path
|
||||
private UnaryOperator<NullPointerState> transfer1 = NullPointerState.identityFunction();
|
||||
|
||||
// used for false case of if clause and exceptional path
|
||||
private UnaryOperator<NullPointerState> transfer2 = NullPointerState.identityFunction();
|
||||
|
||||
// true if sth will change. false => just use identity transfer function.
|
||||
private boolean noIdentity = false;
|
||||
|
||||
private TransferFunctionSSAVisitor(IR ir) {
|
||||
this.sym = ir.getSymbolTable();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayLength(com.ibm.wala.ssa.SSAArrayLengthInstruction)
|
||||
*/
|
||||
public void visitArrayLength(SSAArrayLengthInstruction instruction) {
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getArrayRef());
|
||||
transfer2 = NullPointerState.nullifyFunction(instruction.getArrayRef());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayLoad(com.ibm.wala.ssa.SSAArrayLoadInstruction)
|
||||
*/
|
||||
public void visitArrayLoad(SSAArrayLoadInstruction instruction) {
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getArrayRef());
|
||||
transfer2 = NullPointerState.nullifyFunction(instruction.getArrayRef());
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayLoad(com.ibm.wala.ssa.SSAArrayLoadInstruction)
|
||||
*/
|
||||
public void visitArrayLoad(SSAArrayLoadInstruction instruction) {
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getArrayRef());
|
||||
transfer2 = NullPointerState.nullifyFunction(instruction.getArrayRef());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayStore(com.ibm.wala.ssa.SSAArrayStoreInstruction)
|
||||
*/
|
||||
public void visitArrayStore(SSAArrayStoreInstruction instruction) {
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getArrayRef());
|
||||
transfer2 = NullPointerState.nullifyFunction(instruction.getArrayRef());
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitArrayStore(com.ibm.wala.ssa.SSAArrayStoreInstruction)
|
||||
*/
|
||||
public void visitArrayStore(SSAArrayStoreInstruction instruction) {
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getArrayRef());
|
||||
transfer2 = NullPointerState.nullifyFunction(instruction.getArrayRef());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitBinaryOp(com.ibm.wala.ssa.SSABinaryOpInstruction)
|
||||
*/
|
||||
public void visitBinaryOp(SSABinaryOpInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitBinaryOp(com.ibm.wala.ssa.SSABinaryOpInstruction)
|
||||
*/
|
||||
public void visitBinaryOp(SSABinaryOpInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitCheckCast(com.ibm.wala.ssa.SSACheckCastInstruction)
|
||||
*/
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitCheckCast(com.ibm.wala.ssa.SSACheckCastInstruction)
|
||||
*/
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitComparison(com.ibm.wala.ssa.SSAComparisonInstruction)
|
||||
*/
|
||||
public void visitComparison(SSAComparisonInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitComparison(com.ibm.wala.ssa.SSAComparisonInstruction)
|
||||
*/
|
||||
public void visitComparison(SSAComparisonInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitConditionalBranch(com.ibm.wala.ssa.SSAConditionalBranchInstruction)
|
||||
*/
|
||||
public void visitConditionalBranch(SSAConditionalBranchInstruction instruction) {
|
||||
int arg1 = instruction.getUse(0);
|
||||
int arg2 = instruction.getUse(1);
|
||||
IConditionalBranchInstruction.IOperator testOp = instruction.getOperator();
|
||||
if (!(testOp instanceof IConditionalBranchInstruction.Operator)) {
|
||||
throw new IllegalStateException("Conditional operator of unknown type: " + testOp.getClass());
|
||||
}
|
||||
IConditionalBranchInstruction.Operator op = (IConditionalBranchInstruction.Operator) testOp;
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitConditionalBranch(com.ibm.wala.ssa.SSAConditionalBranchInstruction)
|
||||
*/
|
||||
public void visitConditionalBranch(SSAConditionalBranchInstruction instruction) {
|
||||
int arg1 = instruction.getUse(0);
|
||||
int arg2 = instruction.getUse(1);
|
||||
IConditionalBranchInstruction.IOperator testOp = instruction.getOperator();
|
||||
if (!(testOp instanceof IConditionalBranchInstruction.Operator)) {
|
||||
throw new IllegalStateException("Conditional operator of unknown type: " + testOp.getClass());
|
||||
}
|
||||
IConditionalBranchInstruction.Operator op = (IConditionalBranchInstruction.Operator) testOp;
|
||||
|
||||
if (sym.isNullConstant(arg1)) {
|
||||
switch (op) {
|
||||
case EQ:
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.nullifyFunction(arg2);
|
||||
transfer2 = NullPointerState.denullifyFunction(arg2);
|
||||
break;
|
||||
case NE:
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(arg2);
|
||||
transfer2 = NullPointerState.nullifyFunction(arg2);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Comparision to a null constant using " + op);
|
||||
}
|
||||
} else if (sym.isNullConstant(arg2)) {
|
||||
switch (op) {
|
||||
case EQ:
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.nullifyFunction(arg1);
|
||||
transfer2 = NullPointerState.denullifyFunction(arg1);
|
||||
break;
|
||||
case NE:
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(arg1);
|
||||
transfer2 = NullPointerState.nullifyFunction(arg1);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Comparision to a null constant using " + op);
|
||||
}
|
||||
} else {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
}
|
||||
if (sym.isNullConstant(arg1)) {
|
||||
switch (op) {
|
||||
case EQ:
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.nullifyFunction(arg2);
|
||||
transfer2 = NullPointerState.denullifyFunction(arg2);
|
||||
break;
|
||||
case NE:
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(arg2);
|
||||
transfer2 = NullPointerState.nullifyFunction(arg2);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Comparision to a null constant using " + op);
|
||||
}
|
||||
} else if (sym.isNullConstant(arg2)) {
|
||||
switch (op) {
|
||||
case EQ:
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.nullifyFunction(arg1);
|
||||
transfer2 = NullPointerState.denullifyFunction(arg1);
|
||||
break;
|
||||
case NE:
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(arg1);
|
||||
transfer2 = NullPointerState.nullifyFunction(arg1);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Comparision to a null constant using " + op);
|
||||
}
|
||||
} else {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitConversion(com.ibm.wala.ssa.SSAConversionInstruction)
|
||||
*/
|
||||
public void visitConversion(SSAConversionInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitConversion(com.ibm.wala.ssa.SSAConversionInstruction)
|
||||
*/
|
||||
public void visitConversion(SSAConversionInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGet(com.ibm.wala.ssa.SSAGetInstruction)
|
||||
*/
|
||||
public void visitGet(SSAGetInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
final int ssaVar = instruction.getRef();
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(ssaVar);
|
||||
transfer2 = NullPointerState.nullifyFunction(ssaVar);
|
||||
} else {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGet(com.ibm.wala.ssa.SSAGetInstruction)
|
||||
*/
|
||||
public void visitGet(SSAGetInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
final int ssaVar = instruction.getRef();
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(ssaVar);
|
||||
transfer2 = NullPointerState.nullifyFunction(ssaVar);
|
||||
} else {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGetCaughtException(com.ibm.wala.ssa.SSAGetCaughtExceptionInstruction)
|
||||
*/
|
||||
public void visitGetCaughtException(SSAGetCaughtExceptionInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGetCaughtException(com.ibm.wala.ssa.SSAGetCaughtExceptionInstruction)
|
||||
*/
|
||||
public void visitGetCaughtException(SSAGetCaughtExceptionInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGoto(com.ibm.wala.ssa.SSAGotoInstruction)
|
||||
*/
|
||||
public void visitGoto(SSAGotoInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitGoto(com.ibm.wala.ssa.SSAGotoInstruction)
|
||||
*/
|
||||
public void visitGoto(SSAGotoInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitInstanceof(com.ibm.wala.ssa.SSAInstanceofInstruction)
|
||||
*/
|
||||
public void visitInstanceof(SSAInstanceofInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitInstanceof(com.ibm.wala.ssa.SSAInstanceofInstruction)
|
||||
*/
|
||||
public void visitInstanceof(SSAInstanceofInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitInvoke(com.ibm.wala.ssa.SSAInvokeInstruction)
|
||||
*/
|
||||
public void visitInvoke(SSAInvokeInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
// when no exception is raised on a virtual call, the receiver is not null. Otherwise it is
|
||||
// unsure if the receiver is definitely null as an exception may also stem from the method itself.
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getReceiver());
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
} else {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitInvoke(com.ibm.wala.ssa.SSAInvokeInstruction)
|
||||
*/
|
||||
public void visitInvoke(SSAInvokeInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
// when no exception is raised on a virtual call, the receiver is not null. Otherwise it is
|
||||
// unsure if the receiver is definitely null as an exception may also stem from the method itself.
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getReceiver());
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
} else {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitLoadMetadata(com.ibm.wala.ssa.SSALoadMetadataInstruction)
|
||||
*/
|
||||
public void visitLoadMetadata(SSALoadMetadataInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitLoadMetadata(com.ibm.wala.ssa.SSALoadMetadataInstruction)
|
||||
*/
|
||||
public void visitLoadMetadata(SSALoadMetadataInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitMonitor(com.ibm.wala.ssa.SSAMonitorInstruction)
|
||||
*/
|
||||
public void visitMonitor(SSAMonitorInstruction instruction) {
|
||||
// when no exception is raised on a synchronized statement, the monitor is not null. Otherwise it is
|
||||
// unsure if the monitor is definitely null as other exception may also appear (synchronization related).
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getRef());
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitMonitor(com.ibm.wala.ssa.SSAMonitorInstruction)
|
||||
*/
|
||||
public void visitMonitor(SSAMonitorInstruction instruction) {
|
||||
// when no exception is raised on a synchronized statement, the monitor is not null. Otherwise it is
|
||||
// unsure if the monitor is definitely null as other exception may also appear (synchronization related).
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getRef());
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitNew(com.ibm.wala.ssa.SSANewInstruction)
|
||||
*/
|
||||
public void visitNew(SSANewInstruction instruction) {
|
||||
/*
|
||||
* If an exception is raised upon new is called, then the defined variable
|
||||
* is null else it is guaranteed to not be null.
|
||||
*/
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getDef());
|
||||
transfer2 = NullPointerState.nullifyFunction(instruction.getDef());
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitNew(com.ibm.wala.ssa.SSANewInstruction)
|
||||
*/
|
||||
public void visitNew(SSANewInstruction instruction) {
|
||||
/*
|
||||
* If an exception is raised upon new is called, then the defined variable
|
||||
* is null else it is guaranteed to not be null.
|
||||
*/
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(instruction.getDef());
|
||||
transfer2 = NullPointerState.nullifyFunction(instruction.getDef());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPhi(com.ibm.wala.ssa.SSAPhiInstruction)
|
||||
*/
|
||||
public void visitPhi(SSAPhiInstruction instruction) {
|
||||
noIdentity = true;
|
||||
int[] uses = new int[instruction.getNumberOfUses()];
|
||||
for (int i = 0; i < uses.length; i++) {
|
||||
uses[i] = instruction.getUse(i);
|
||||
}
|
||||
|
||||
transfer1 = NullPointerState.phiValueMeetFunction(instruction.getDef(), uses);
|
||||
// should not be used as no alternative path exists
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPhi(com.ibm.wala.ssa.SSAPhiInstruction)
|
||||
*/
|
||||
public void visitPhi(SSAPhiInstruction instruction) {
|
||||
noIdentity = true;
|
||||
int[] uses = new int[instruction.getNumberOfUses()];
|
||||
for (int i = 0; i < uses.length; i++) {
|
||||
uses[i] = instruction.getUse(i);
|
||||
}
|
||||
|
||||
transfer1 = NullPointerState.phiValueMeetFunction(instruction.getDef(), uses);
|
||||
// should not be used as no alternative path exists
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPi(com.ibm.wala.ssa.SSAPiInstruction)
|
||||
*/
|
||||
public void visitPi(SSAPiInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPi(com.ibm.wala.ssa.SSAPiInstruction)
|
||||
*/
|
||||
public void visitPi(SSAPiInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPut(com.ibm.wala.ssa.SSAPutInstruction)
|
||||
*/
|
||||
public void visitPut(SSAPutInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
final int ssaVar = instruction.getRef();
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(ssaVar);
|
||||
transfer2 = NullPointerState.nullifyFunction(ssaVar);
|
||||
} else {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitPut(com.ibm.wala.ssa.SSAPutInstruction)
|
||||
*/
|
||||
public void visitPut(SSAPutInstruction instruction) {
|
||||
if (!instruction.isStatic()) {
|
||||
final int ssaVar = instruction.getRef();
|
||||
noIdentity = true;
|
||||
transfer1 = NullPointerState.denullifyFunction(ssaVar);
|
||||
transfer2 = NullPointerState.nullifyFunction(ssaVar);
|
||||
} else {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitReturn(com.ibm.wala.ssa.SSAReturnInstruction)
|
||||
*/
|
||||
public void visitReturn(SSAReturnInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitReturn(com.ibm.wala.ssa.SSAReturnInstruction)
|
||||
*/
|
||||
public void visitReturn(SSAReturnInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitSwitch(com.ibm.wala.ssa.SSASwitchInstruction)
|
||||
*/
|
||||
public void visitSwitch(SSASwitchInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitSwitch(com.ibm.wala.ssa.SSASwitchInstruction)
|
||||
*/
|
||||
public void visitSwitch(SSASwitchInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitThrow(com.ibm.wala.ssa.SSAThrowInstruction)
|
||||
*/
|
||||
public void visitThrow(SSAThrowInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitThrow(com.ibm.wala.ssa.SSAThrowInstruction)
|
||||
*/
|
||||
public void visitThrow(SSAThrowInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitUnaryOp(com.ibm.wala.ssa.SSAUnaryOpInstruction)
|
||||
*/
|
||||
public void visitUnaryOp(SSAUnaryOpInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see com.ibm.wala.ssa.SSAInstruction.IVisitor#visitUnaryOp(com.ibm.wala.ssa.SSAUnaryOpInstruction)
|
||||
*/
|
||||
public void visitUnaryOp(SSAUnaryOpInstruction instruction) {
|
||||
noIdentity = false;
|
||||
transfer1 = NullPointerState.identityFunction();
|
||||
transfer2 = NullPointerState.identityFunction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,117 +14,117 @@ import com.ibm.wala.fixpoint.AbstractVariable;
|
|||
*
|
||||
*/
|
||||
public class ParameterState extends AbstractVariable<ParameterState> {
|
||||
/*
|
||||
* Inital state is UNKNOWN.
|
||||
* Lattice: UNKNOWN < { NULL, NOT_NULL } < BOTH
|
||||
*
|
||||
* public enum State { UNKNOWN, BOTH, NULL, NOT_NULL }; as defined in EdgeState
|
||||
*
|
||||
*/
|
||||
|
||||
public static final int NO_THIS_PTR = -1;
|
||||
|
||||
// maps the parmeter's varNum --> State
|
||||
private final HashMap<Integer, State> params = new HashMap<Integer, State>();
|
||||
|
||||
public static ParameterState createDefault(IMethod m) {
|
||||
ParameterState p = new ParameterState();
|
||||
|
||||
if (!m.isStatic()) {
|
||||
// set this pointer to NOT_NULL
|
||||
p.setState(0, State.NOT_NULL);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
public ParameterState() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to make a <code>ParameteState</code> out of a regular <code>EdgeState</code>.
|
||||
*
|
||||
* @param state The <code>EdgeState</code> to parse.
|
||||
* @param parameterNumbers The numbers of parameters in <code>state</code>
|
||||
*/
|
||||
public ParameterState(NullPointerState state, int[] parameterNumbers) {
|
||||
//by convention the first ssa vars are the parameters
|
||||
for (int i=1; i < parameterNumbers.length; i++){
|
||||
params.put(i, state.getState(parameterNumbers[i]));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Inital state is UNKNOWN.
|
||||
* Lattice: UNKNOWN < { NULL, NOT_NULL } < BOTH
|
||||
*
|
||||
* public enum State { UNKNOWN, BOTH, NULL, NOT_NULL }; as defined in NullPointerState
|
||||
*
|
||||
*/
|
||||
|
||||
public static final int NO_THIS_PTR = -1;
|
||||
|
||||
// maps the parmeter's varNum --> State
|
||||
private final HashMap<Integer, State> params = new HashMap<Integer, State>();
|
||||
|
||||
public static ParameterState createDefault(IMethod m) {
|
||||
ParameterState p = new ParameterState();
|
||||
|
||||
if (!m.isStatic()) {
|
||||
// set this pointer to NOT_NULL
|
||||
p.setState(0, State.NOT_NULL);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
public ParameterState() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to make a <code>ParameteState</code> out of a regular <code>NullPointerState</code>.
|
||||
*
|
||||
* @param state The <code>NullPointerState</code> to parse.
|
||||
* @param parameterNumbers The numbers of parameters in <code>state</code>
|
||||
*/
|
||||
public ParameterState(NullPointerState state, int[] parameterNumbers) {
|
||||
//by convention the first ssa vars are the parameters
|
||||
for (int i=1; i < parameterNumbers.length; i++){
|
||||
params.put(i, state.getState(parameterNumbers[i]));
|
||||
}
|
||||
}
|
||||
|
||||
public void setState(int varNum, State state) {
|
||||
State prev = params.get(varNum);
|
||||
if (prev != null) {
|
||||
switch (prev) {
|
||||
case BOTH:
|
||||
if (state != State.BOTH) {
|
||||
throw new IllegalArgumentException("Try to set " + prev + " to " + state);
|
||||
}
|
||||
break;
|
||||
case NULL:
|
||||
if (!(state == State.BOTH || state == State.NULL)) {
|
||||
throw new IllegalArgumentException("Try to set " + prev + " to " + state);
|
||||
}
|
||||
break;
|
||||
case NOT_NULL:
|
||||
if (!(state == State.BOTH || state == State.NOT_NULL)) {
|
||||
throw new IllegalArgumentException("Try to set " + prev + " to " + state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
params.put(varNum, state);
|
||||
}
|
||||
|
||||
public HashMap<Integer, State> getStates() {
|
||||
return this.params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state of an specified parameter.
|
||||
*
|
||||
* @param varNum The SSA var num of the parameter
|
||||
* @return the state of the parameter defined with <code>varNum</code>
|
||||
*/
|
||||
public State getState(int varNum) {
|
||||
State state = params.get(varNum);
|
||||
return (state == null ? State.UNKNOWN : state);
|
||||
}
|
||||
public void setState(int varNum, State state) {
|
||||
State prev = params.get(varNum);
|
||||
if (prev != null) {
|
||||
switch (prev) {
|
||||
case BOTH:
|
||||
if (state != State.BOTH) {
|
||||
throw new IllegalArgumentException("Try to set " + prev + " to " + state);
|
||||
}
|
||||
break;
|
||||
case NULL:
|
||||
if (!(state == State.BOTH || state == State.NULL)) {
|
||||
throw new IllegalArgumentException("Try to set " + prev + " to " + state);
|
||||
}
|
||||
break;
|
||||
case NOT_NULL:
|
||||
if (!(state == State.BOTH || state == State.NOT_NULL)) {
|
||||
throw new IllegalArgumentException("Try to set " + prev + " to " + state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
params.put(varNum, state);
|
||||
}
|
||||
|
||||
public HashMap<Integer, State> getStates() {
|
||||
return this.params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state of an specified parameter.
|
||||
*
|
||||
* @param varNum The SSA var num of the parameter
|
||||
* @return the state of the parameter defined with <code>varNum</code>
|
||||
*/
|
||||
public State getState(int varNum) {
|
||||
State state = params.get(varNum);
|
||||
return (state == null ? State.UNKNOWN : state);
|
||||
}
|
||||
|
||||
public void copyState(ParameterState v) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer("<");
|
||||
Set<Entry<Integer, State>> paramsSet = params.entrySet();
|
||||
|
||||
for (Entry<Integer, State> param : paramsSet){
|
||||
switch (param.getValue()) {
|
||||
case BOTH:
|
||||
buf.append('*');
|
||||
break;
|
||||
case NOT_NULL:
|
||||
buf.append('1');
|
||||
break;
|
||||
case NULL:
|
||||
buf.append('0');
|
||||
break;
|
||||
case UNKNOWN:
|
||||
buf.append('?');
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
buf.append('>');
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
public void copyState(ParameterState v) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer("<");
|
||||
Set<Entry<Integer, State>> paramsSet = params.entrySet();
|
||||
|
||||
for (Entry<Integer, State> param : paramsSet){
|
||||
switch (param.getValue()) {
|
||||
case BOTH:
|
||||
buf.append('*');
|
||||
break;
|
||||
case NOT_NULL:
|
||||
buf.append('1');
|
||||
break;
|
||||
case NULL:
|
||||
buf.append('0');
|
||||
break;
|
||||
case UNKNOWN:
|
||||
buf.append('?');
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
buf.append('>');
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,18 +27,11 @@ public class SSACFGNullPointerAnalysis implements ExceptionPruningAnalysis<SSAIn
|
|||
this.mState = (mState == null ? MethodState.DEFAULT : mState);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see jsdg.exceptions.ExceptionPrunedCFGAnalysis#getOriginal()
|
||||
*/
|
||||
public ControlFlowGraph<SSAInstruction, ISSABasicBlock> getOriginal() {
|
||||
return ir.getControlFlowGraph();
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.cfg.exc.ExceptionPruningAnalysis#compute(com.ibm.wala.util.MonitorUtil.IProgressMonitor)
|
||||
*/
|
||||
public int compute(IProgressMonitor progress) throws UnsoundGraphException, CancelException {
|
||||
ControlFlowGraph<SSAInstruction, ISSABasicBlock> orig = getOriginal();
|
||||
ControlFlowGraph<SSAInstruction, ISSABasicBlock> orig = ir.getControlFlowGraph();
|
||||
|
||||
intra = new IntraprocNullPointerAnalysis<ISSABasicBlock>(ir, orig, ignoredExceptions, initialState, mState);
|
||||
intra.run(progress);
|
||||
|
@ -54,7 +47,7 @@ public class SSACFGNullPointerAnalysis implements ExceptionPruningAnalysis<SSAIn
|
|||
throw new IllegalStateException("Run compute(IProgressMonitor) first.");
|
||||
}
|
||||
|
||||
return intra.getPrunedCfg();
|
||||
return intra.getPrunedCFG();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -65,7 +58,7 @@ public class SSACFGNullPointerAnalysis implements ExceptionPruningAnalysis<SSAIn
|
|||
throw new IllegalStateException("Run compute(IProgressMonitor) first.");
|
||||
}
|
||||
|
||||
ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg = intra.getPrunedCfg();
|
||||
ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg = intra.getPrunedCFG();
|
||||
|
||||
boolean hasException = false;
|
||||
for (ISSABasicBlock bb : cfg) {
|
||||
|
|
Loading…
Reference in New Issue