Bugfixes, code and documentation improvements.
This commit is contained in:
parent
0387bd1591
commit
2869af24df
|
@ -11,6 +11,7 @@ Require-Bundle: com.ibm.wala.shrike,
|
|||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: .,
|
||||
com.ibm.wala.analysis.arraybounds,
|
||||
com.ibm.wala.analysis.exceptionanalysis,
|
||||
com.ibm.wala.analysis.nullpointer,
|
||||
com.ibm.wala.analysis.pointers,
|
||||
com.ibm.wala.analysis.reflection,
|
||||
|
@ -43,6 +44,7 @@ Export-Package: .,
|
|||
com.ibm.wala.ipa.cfg,
|
||||
com.ibm.wala.ipa.cfg.exceptionpruning,
|
||||
com.ibm.wala.ipa.cfg.exceptionpruning.filter,
|
||||
com.ibm.wala.ipa.cfg.exceptionpruning.interprocedural,
|
||||
com.ibm.wala.ipa.cha,
|
||||
com.ibm.wala.ipa.modref,
|
||||
com.ibm.wala.ipa.slicer,
|
||||
|
|
|
@ -24,6 +24,12 @@ import com.ibm.wala.ipa.cha.ClassHierarchy;
|
|||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
/**
|
||||
* Wrapper to store multiple intraprocedural analysis for a call graph.
|
||||
*
|
||||
* @author Stephan Gocht <stephan@gobro.de>
|
||||
*
|
||||
*/
|
||||
public class CGIntraproceduralExceptionAnalysis {
|
||||
private Map<CGNode, IntraproceduralExceptionAnalysis> analysis;
|
||||
private Set<TypeReference> exceptions;
|
||||
|
@ -34,10 +40,10 @@ public class CGIntraproceduralExceptionAnalysis {
|
|||
this.callGraph = cg;
|
||||
this.exceptions = new LinkedHashSet<>();
|
||||
this.analysis = new LinkedHashMap<>();
|
||||
for (CGNode node : cg) {
|
||||
if (node.getIR() == null || node.getIR().isEmptyIR()) {
|
||||
for (CGNode node : cg) {
|
||||
if (node.getIR() == null || node.getIR().isEmptyIR()) {
|
||||
analysis.put(node, IntraproceduralExceptionAnalysis.newDummy());
|
||||
} else {
|
||||
} else {
|
||||
IntraproceduralExceptionAnalysis intraEA;
|
||||
intraEA = new IntraproceduralExceptionAnalysis(node, filter.getFilter(node), cha, pointerAnalysis);
|
||||
analysis.put(node, intraEA);
|
||||
|
|
|
@ -26,7 +26,7 @@ public class Exception2BitvectorTransformer {
|
|||
return values;
|
||||
}
|
||||
|
||||
public Exception2BitvectorTransformer(Set<TypeReference> exceptions) {
|
||||
public Exception2BitvectorTransformer(Set<TypeReference> exceptions) {
|
||||
createValues(exceptions);
|
||||
for (TypeReference exception : exceptions) {
|
||||
BitVector bv = new BitVector(values.getSize());
|
||||
|
@ -48,7 +48,7 @@ public class Exception2BitvectorTransformer {
|
|||
result.set(pos);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Got exception I don't know about,"
|
||||
+ "make sure only to use exceptions given to the constructor ");
|
||||
+ "make sure only to use exceptions given to the constructor ");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -10,8 +10,12 @@
|
|||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.exceptionanalysis;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.analysis.arraybounds.ArrayOutOfBoundsAnalysis;
|
||||
import com.ibm.wala.analysis.nullpointer.IntraproceduralNullPointerAnalysis;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorFramework;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
||||
import com.ibm.wala.fixpoint.BitVectorVariable;
|
||||
|
@ -19,26 +23,72 @@ import com.ibm.wala.ipa.callgraph.CGNode;
|
|||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.ExceptionFilter;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.ExceptionMatcher;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.filter.DummyFilter;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.interprocedural.IgnoreExceptionsInterFilter;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.interprocedural.InterproceduralExceptionFilter;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.ISSABasicBlock;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction.Visitor;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
|
||||
import com.ibm.wala.util.graph.Graph;
|
||||
import com.ibm.wala.util.graph.impl.InvertedGraph;
|
||||
|
||||
/**
|
||||
*
|
||||
* This class analyzes the exceptional control flow. Use
|
||||
* {@link ExceptionAnalysis2EdgeFilter} to remove infeasible edges.
|
||||
*
|
||||
* In a first step an intraprocedural analysis is performed, to collect the
|
||||
* thrown exceptions and collect the exceptions caught, per invoke instruction.
|
||||
* The results of the intraprocedural analysis are used for a GenKill data flow
|
||||
* analysis on the call graph. (Each node generates intraprocedural thrown
|
||||
* exceptions and along invoke edges, caught exceptions are removed.)
|
||||
*
|
||||
* Notice: Only exceptions, which are part of the analysis scope are considered.
|
||||
*
|
||||
* @author Stephan Gocht <stephan@gobro.de>
|
||||
*
|
||||
*/
|
||||
public class ExceptionAnalysis {
|
||||
private BitVectorSolver<CGNode> solver;
|
||||
private Exception2BitvectorTransformer transformer;
|
||||
private InterproceduralExceptionFilter<SSAInstruction> filter;
|
||||
private ClassHierarchy cha;
|
||||
private CGIntraproceduralExceptionAnalysis intraResult;
|
||||
private CallGraph cg;
|
||||
private boolean isSolved = false;
|
||||
|
||||
public ExceptionAnalysis(CallGraph callgraph, PointerAnalysis<InstanceKey> pointerAnalysis, ClassHierarchy cha) {
|
||||
this(callgraph, pointerAnalysis, cha, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callgraph
|
||||
* @param pointerAnalysis
|
||||
* @param cha
|
||||
* @param filter
|
||||
* a filter to include results of other analysis (like
|
||||
* {@link ArrayOutOfBoundsAnalysis} or
|
||||
* {@link IntraproceduralNullPointerAnalysis}) or to ignore
|
||||
* exceptions completely.
|
||||
*/
|
||||
public ExceptionAnalysis(CallGraph callgraph, PointerAnalysis<InstanceKey> pointerAnalysis, ClassHierarchy cha,
|
||||
InterproceduralExceptionFilter<SSAInstruction> filter) {
|
||||
CGIntraproceduralExceptionAnalysis intraResult = new CGIntraproceduralExceptionAnalysis(callgraph, pointerAnalysis, cha, filter);
|
||||
this.cha = cha;
|
||||
this.cg = callgraph;
|
||||
if (filter == null) {
|
||||
this.filter = new IgnoreExceptionsInterFilter<>(new DummyFilter<SSAInstruction>());
|
||||
} else {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
intraResult = new CGIntraproceduralExceptionAnalysis(callgraph, pointerAnalysis, cha, this.filter);
|
||||
transformer = new Exception2BitvectorTransformer(intraResult.getExceptions());
|
||||
ExceptionTransferFunctionProvider transferFunctionProvider = new ExceptionTransferFunctionProvider(intraResult, callgraph,
|
||||
transformer);
|
||||
|
@ -55,16 +105,125 @@ public class ExceptionAnalysis {
|
|||
try {
|
||||
solver.solve(null);
|
||||
} catch (CancelException e) {
|
||||
throw new RuntimeException("Internal Error: Got Cancel Exception, "
|
||||
+ "but didn't use Progressmonitor!", e);
|
||||
throw new RuntimeException("Internal Error: Got Cancel Exception, " + "but didn't use Progressmonitor!", e);
|
||||
}
|
||||
this.isSolved = true;
|
||||
}
|
||||
|
||||
public void solve(IProgressMonitor monitor) throws CancelException {
|
||||
solver.solve(monitor);
|
||||
this.isSolved = true;
|
||||
}
|
||||
|
||||
public boolean catchesException(CGNode node, ISSABasicBlock throwBlock, ISSABasicBlock catchBlock) {
|
||||
if (!isSolved) {
|
||||
throw new IllegalStateException("You need to use .solve() first!");
|
||||
}
|
||||
|
||||
if (node.getIR().getControlFlowGraph().getExceptionalSuccessors(throwBlock).contains(catchBlock) && catchBlock.isCatchBlock()) {
|
||||
SSAInstruction instruction = IntraproceduralExceptionAnalysis.getThrowingInstruction(throwBlock);
|
||||
assert instruction != null;
|
||||
Iterator<TypeReference> caughtExceptions = catchBlock.getCaughtExceptionTypes();
|
||||
Set<TypeReference> thrownExceptions = this.getExceptions(node, instruction);
|
||||
boolean isCaught = false;
|
||||
while (caughtExceptions.hasNext() && !isCaught) {
|
||||
TypeReference caughtException = caughtExceptions.next();
|
||||
for (TypeReference thrownException : thrownExceptions) {
|
||||
isCaught |= cha.isAssignableFrom(cha.lookupClass(caughtException), cha.lookupClass(thrownException));
|
||||
if (isCaught)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isCaught;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void solve(IProgressMonitor monitor) throws CancelException {
|
||||
solver.solve(monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node
|
||||
* @param block
|
||||
* @return if the block has uncaught exceptions
|
||||
*/
|
||||
public boolean hasUncaughtExceptions(CGNode node, ISSABasicBlock block) {
|
||||
if (!isSolved) {
|
||||
throw new IllegalStateException("You need to use .solve() first!");
|
||||
}
|
||||
|
||||
SSAInstruction instruction = IntraproceduralExceptionAnalysis.getThrowingInstruction(block);
|
||||
if (instruction != null) {
|
||||
Set<TypeReference> exceptions = this.getExceptions(node, instruction);
|
||||
|
||||
boolean allCaught = true;
|
||||
for (TypeReference thrownException : exceptions) {
|
||||
boolean isCaught = false;
|
||||
for (ISSABasicBlock catchBlock : node.getIR().getControlFlowGraph().getExceptionalSuccessors(block)) {
|
||||
Iterator<TypeReference> caughtExceptions = catchBlock.getCaughtExceptionTypes();
|
||||
while (caughtExceptions.hasNext() && !isCaught) {
|
||||
TypeReference caughtException = caughtExceptions.next();
|
||||
isCaught |= cha.isAssignableFrom(cha.lookupClass(caughtException), cha.lookupClass(thrownException));
|
||||
if (isCaught)
|
||||
break;
|
||||
}
|
||||
if (isCaught)
|
||||
break;
|
||||
}
|
||||
allCaught &= isCaught;
|
||||
if (!allCaught)
|
||||
break;
|
||||
}
|
||||
|
||||
return !allCaught;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all exceptions, which may be raised by this instruction. This
|
||||
* includes exceptions from throw and invoke statements.
|
||||
*
|
||||
* @param node
|
||||
* @param instruction
|
||||
* @return all exceptions, which may be raised by this instruction
|
||||
*/
|
||||
public Set<TypeReference> getExceptions(final CGNode node, SSAInstruction instruction) {
|
||||
if (!isSolved) {
|
||||
throw new IllegalStateException("You need to use .solve() first!");
|
||||
}
|
||||
|
||||
final Set<TypeReference> thrown = intraResult.getAnalysis(node).collectThrownExceptions(instruction);
|
||||
|
||||
instruction.visit(new Visitor() {
|
||||
@Override
|
||||
public void visitInvoke(SSAInvokeInstruction instruction) {
|
||||
CallSiteReference site = instruction.getCallSite();
|
||||
Set<CGNode> targets = cg.getPossibleTargets(node, site);
|
||||
for (CGNode target : targets) {
|
||||
thrown.addAll(getCGNodeExceptions(target));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Set<TypeReference> result = thrown;
|
||||
if (filter != null) {
|
||||
ExceptionFilter<SSAInstruction> nodeFilter = filter.getFilter(node);
|
||||
result = ExceptionMatcher.retainedExceptions(thrown, nodeFilter.filteredExceptions(instruction), cha);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param node
|
||||
* @return all exceptions, which might be thrown by the method represented
|
||||
* through the call graph node.
|
||||
*/
|
||||
public Set<TypeReference> getCGNodeExceptions(CGNode node) {
|
||||
if (!isSolved) {
|
||||
throw new IllegalStateException("You need to use .solve() first!");
|
||||
}
|
||||
|
||||
BitVectorVariable nodeResult = solver.getOut(node);
|
||||
if (nodeResult != null) {
|
||||
return transformer.computeExceptions(nodeResult);
|
||||
|
@ -72,4 +231,15 @@ public class ExceptionAnalysis {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the used filter
|
||||
*/
|
||||
public InterproceduralExceptionFilter<SSAInstruction> getFilter() {
|
||||
if (!isSolved) {
|
||||
throw new IllegalStateException("You need to use .solve() first!");
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.exceptionanalysis;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.cfg.EdgeFilter;
|
||||
import com.ibm.wala.ssa.ISSABasicBlock;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
|
||||
/**
|
||||
* Converter to use the results of the exception analysis with an edge filter.
|
||||
*
|
||||
* @author Stephan Gocht <stephan@gobro.de>
|
||||
*
|
||||
*/
|
||||
public class ExceptionAnalysis2EdgeFilter implements EdgeFilter<ISSABasicBlock> {
|
||||
private ExceptionAnalysis analysis;
|
||||
private CGNode node;
|
||||
|
||||
public ExceptionAnalysis2EdgeFilter(ExceptionAnalysis analysis, CGNode node) {
|
||||
this.analysis = analysis;
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNormalEdge(ISSABasicBlock src, ISSABasicBlock dst) {
|
||||
boolean originalEdge = node.getIR().getControlFlowGraph().getNormalSuccessors(src).contains(dst);
|
||||
boolean result = originalEdge;
|
||||
SSAInstruction instruction = IntraproceduralExceptionAnalysis.getThrowingInstruction(src);
|
||||
if (instruction != null) {
|
||||
if (analysis.getFilter().getFilter(node).alwaysThrowsException(instruction)) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasExceptionalEdge(ISSABasicBlock src, ISSABasicBlock dst) {
|
||||
boolean originalEdge = node.getIR().getControlFlowGraph().getExceptionalSuccessors(src).contains(dst);
|
||||
boolean result = originalEdge;
|
||||
|
||||
if (dst.isCatchBlock()) {
|
||||
if (!analysis.catchesException(node, src, dst)) {
|
||||
result = false;
|
||||
}
|
||||
} else {
|
||||
assert dst.isExitBlock();
|
||||
result = analysis.hasUncaughtExceptions(node, src);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -70,19 +70,18 @@ public class ExceptionTransferFunctionProvider implements ITransferFunctionProvi
|
|||
|
||||
Iterator<CallSiteReference> callsites = cg.getPossibleSites(src, dst);
|
||||
BitVector filtered = new BitVector(transformer.getValues().getSize());
|
||||
|
||||
|
||||
|
||||
if (callsites.hasNext()) {
|
||||
|
||||
|
||||
CallSiteReference callsite = callsites.next();
|
||||
|
||||
Set<TypeReference> caught = new LinkedHashSet<>();
|
||||
caught.addAll(intraResult.getAnalysis(src).getCaughtExceptions(callsite));
|
||||
|
||||
Set<TypeReference> caught = new LinkedHashSet<>();
|
||||
caught.addAll(intraResult.getAnalysis(src).getCaughtExceptions(callsite));
|
||||
while (callsites.hasNext()) {
|
||||
callsite = callsites.next();
|
||||
caught.retainAll(intraResult.getAnalysis(src).getCaughtExceptions(callsite));
|
||||
}
|
||||
|
||||
|
||||
filtered = transformer.computeBitVector(caught);
|
||||
return new BitVectorMinusVector(filtered);
|
||||
} else {
|
||||
|
|
|
@ -30,8 +30,8 @@ public class InitializedBitVectorSolver extends BitVectorSolver<CGNode> {
|
|||
protected BitVectorVariable makeEdgeVariable(CGNode src, CGNode dst) {
|
||||
return newBV();
|
||||
}
|
||||
|
||||
private BitVectorVariable newBV(){
|
||||
|
||||
private BitVectorVariable newBV() {
|
||||
/*
|
||||
* If we do not initialize BitVectorVariable, with a BitVector, it contains
|
||||
* null, which may crash in combination with {@link BitVectorMinusVector}
|
||||
|
@ -39,6 +39,6 @@ public class InitializedBitVectorSolver extends BitVectorSolver<CGNode> {
|
|||
*/
|
||||
BitVectorVariable result = new BitVectorVariable();
|
||||
result.addAll(new BitVector());
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.Collections;
|
|||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
|
@ -35,6 +36,7 @@ import com.ibm.wala.ssa.SSAInstruction.Visitor;
|
|||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.intset.IntIterator;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
import com.ibm.wala.util.ssa.InstructionByIIndexMap;
|
||||
|
||||
public class IntraproceduralExceptionAnalysis {
|
||||
private Set<TypeReference> exceptions;
|
||||
|
@ -45,6 +47,7 @@ public class IntraproceduralExceptionAnalysis {
|
|||
private ExceptionFilter<SSAInstruction> filter;
|
||||
private IR ir;
|
||||
private boolean dummy = false;
|
||||
private Map<SSAInstruction, Boolean> allExceptionsCaught;
|
||||
|
||||
public static IntraproceduralExceptionAnalysis newDummy() {
|
||||
return new IntraproceduralExceptionAnalysis();
|
||||
|
@ -104,10 +107,8 @@ public class IntraproceduralExceptionAnalysis {
|
|||
this.node = node;
|
||||
this.exceptions = new LinkedHashSet<>();
|
||||
this.possiblyCaughtExceptions = new LinkedHashSet<>();
|
||||
this.allExceptionsCaught = new InstructionByIIndexMap<>();
|
||||
compute();
|
||||
this.filter = null;
|
||||
this.pointerAnalysis = null;
|
||||
this.node = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,25 +120,26 @@ public class IntraproceduralExceptionAnalysis {
|
|||
if (ir != null) {
|
||||
for (ISSABasicBlock block : ir.getControlFlowGraph()) {
|
||||
SSAInstruction throwingInstruction = getThrowingInstruction(block);
|
||||
if (throwingInstruction != null) {
|
||||
if (throwingInstruction != null && throwingInstruction.isPEI()) {
|
||||
Set<TypeReference> thrownExceptions = collectThrownExceptions(throwingInstruction);
|
||||
Set<TypeReference> caughtExceptions = collectCaughtExceptions(block);
|
||||
Set<TypeReference> filteredExceptions = collectFilteredExceptions(throwingInstruction);
|
||||
|
||||
thrownExceptions.removeAll(filteredExceptions);
|
||||
thrownExceptions.removeAll(caughtExceptions);
|
||||
this.allExceptionsCaught.put(throwingInstruction, thrownExceptions.isEmpty());
|
||||
exceptions.addAll(thrownExceptions);
|
||||
}
|
||||
|
||||
|
||||
if (block.isCatchBlock()) {
|
||||
Iterator<TypeReference> it = block.getCaughtExceptionTypes();
|
||||
while (it.hasNext()) {
|
||||
Iterator<TypeReference> it = block.getCaughtExceptionTypes();
|
||||
while (it.hasNext()) {
|
||||
possiblyCaughtExceptions.add(it.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Set<TypeReference> subClasses = new LinkedHashSet<>();
|
||||
for (TypeReference caught : possiblyCaughtExceptions) {
|
||||
for (IClass iclass : this.classHierachy.computeSubClasses(caught)) {
|
||||
|
@ -150,6 +152,7 @@ public class IntraproceduralExceptionAnalysis {
|
|||
|
||||
/**
|
||||
* Return all exceptions that could be returned from getCaughtExceptions
|
||||
*
|
||||
* @return all exceptions that could be returned from getCaughtExceptions
|
||||
*/
|
||||
public Set<TypeReference> getPossiblyCaughtExceptions() {
|
||||
|
@ -194,7 +197,7 @@ public class IntraproceduralExceptionAnalysis {
|
|||
* @return a set of exceptions, which might be thrown from this instruction
|
||||
* within this method
|
||||
*/
|
||||
private Set<TypeReference> collectThrownExceptions(SSAInstruction throwingInstruction) {
|
||||
public Set<TypeReference> collectThrownExceptions(SSAInstruction throwingInstruction) {
|
||||
final LinkedHashSet<TypeReference> result = new LinkedHashSet<>();
|
||||
result.addAll(throwingInstruction.getExceptionTypes());
|
||||
|
||||
|
@ -243,11 +246,11 @@ public class IntraproceduralExceptionAnalysis {
|
|||
* @return an instruction which may throw exceptions, or null if this block
|
||||
* can't throw exceptions
|
||||
*/
|
||||
private SSAInstruction getThrowingInstruction(ISSABasicBlock block) {
|
||||
public static SSAInstruction getThrowingInstruction(ISSABasicBlock block) {
|
||||
SSAInstruction result = null;
|
||||
if (block.getLastInstructionIndex() >= 0) {
|
||||
SSAInstruction lastInstruction = block.getLastInstruction();
|
||||
if (lastInstruction != null) {
|
||||
if (lastInstruction != null && lastInstruction.isPEI()) {
|
||||
result = lastInstruction;
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +285,6 @@ public class IntraproceduralExceptionAnalysis {
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all exceptions for the given call site in the given call graph
|
||||
* node, which will be caught.
|
||||
|
@ -317,6 +319,11 @@ public class IntraproceduralExceptionAnalysis {
|
|||
return result;
|
||||
}
|
||||
|
||||
public boolean hasUncaughtExceptions(SSAInstruction instruction) {
|
||||
Boolean allCaught = this.allExceptionsCaught.get(instruction);
|
||||
return (allCaught == null ? true : !allCaught.booleanValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all exceptions which might be created and thrown but not caught or
|
||||
* filtered. (So this does not contain exceptions from invoked methods.)
|
||||
|
|
|
@ -1,2 +1,8 @@
|
|||
/**
|
||||
* This package contains an exception analysis. For an interprocedural
|
||||
* exception analysis use {@link com.ibm.wala.analysis.exceptionanalysis.ExceptionAnalysis}.
|
||||
* If you need a CFG without unnecessary exception edges use {@link com.ibm.wala.ipa.cfg.PrunedCFG}
|
||||
* in combination with {@link com.ibm.wala.analysis.exceptionanalysis.ExceptionAnalysis2EdgeFilter}
|
||||
|
||||
*/
|
||||
package com.ibm.wala.analysis.exceptionanalysis;
|
|
@ -1,7 +1,7 @@
|
|||
package com.ibm.wala.ipa.cfg.exceptionpruning;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
|
@ -29,37 +29,49 @@ public class ExceptionMatcher {
|
|||
filteredExceptions, cha);
|
||||
return matcher.areAllExceptionsIgnored();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all exceptions of thrownExceptions which are not filtered by filteredExceptions
|
||||
* @param thrownExceptions
|
||||
* @param filteredExceptions
|
||||
* @param cha
|
||||
* @return all exceptions of thrownExceptions which are not filtered by filteredExceptions
|
||||
*/
|
||||
public static Set<TypeReference> retainedExceptions(Collection<TypeReference> thrownExceptions,
|
||||
Collection<FilteredException> filteredExceptions, ClassHierarchy cha){
|
||||
final ExceptionMatcher matcher = new ExceptionMatcher(thrownExceptions,
|
||||
filteredExceptions, cha);
|
||||
return matcher.getRetainedExceptions();
|
||||
}
|
||||
|
||||
private Set<TypeReference> ignoreExact;
|
||||
private Set<TypeReference> ignoreSubclass;
|
||||
private final Set<TypeReference> retainedExceptions;
|
||||
private ClassHierarchy cha;
|
||||
|
||||
private final boolean areAllExceptionsIgnored;
|
||||
|
||||
private ExceptionMatcher(Collection<TypeReference> thrownExceptions,
|
||||
Collection<FilteredException> filteredExceptions, ClassHierarchy cha) {
|
||||
this.ignoreExact = new HashSet<>();
|
||||
this.ignoreSubclass = new HashSet<>();
|
||||
this.ignoreExact = new LinkedHashSet<>();
|
||||
this.ignoreSubclass = new LinkedHashSet<>();
|
||||
this.cha = cha;
|
||||
this.retainedExceptions = new LinkedHashSet<>();
|
||||
|
||||
this.fillIgnore(filteredExceptions);
|
||||
|
||||
this.areAllExceptionsIgnored = this
|
||||
.allExceptionsIgnored(thrownExceptions);
|
||||
this.computeRetainedExceptions(thrownExceptions);
|
||||
this.areAllExceptionsIgnored = this.retainedExceptions.isEmpty();
|
||||
|
||||
this.free();
|
||||
}
|
||||
|
||||
private boolean allExceptionsIgnored(
|
||||
Collection<TypeReference> thrownExceptions) {
|
||||
boolean allExceptionsIgnored = true;
|
||||
for (final TypeReference exception : thrownExceptions) {
|
||||
allExceptionsIgnored &= this.isFiltered(exception);
|
||||
if (!allExceptionsIgnored) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return allExceptionsIgnored;
|
||||
private void computeRetainedExceptions(Collection<TypeReference> thrownExceptions){
|
||||
for (final TypeReference exception : thrownExceptions) {
|
||||
if (!this.isFiltered(exception)) {
|
||||
this.retainedExceptions.add(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean areAllExceptionsIgnored() {
|
||||
|
@ -108,4 +120,8 @@ public class ExceptionMatcher {
|
|||
|
||||
return isFiltered;
|
||||
}
|
||||
|
||||
public Set<TypeReference> getRetainedExceptions() {
|
||||
return retainedExceptions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 IBM Corporation.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package com.ibm.wala.ipa.cfg.exceptionpruning.filter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.ExceptionFilter;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.FilteredException;
|
||||
|
||||
public class DummyFilter<Instruction> implements ExceptionFilter<Instruction>{
|
||||
@Override
|
||||
public boolean alwaysThrowsException(Instruction instruction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FilteredException> filteredExceptions(Instruction instruction) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue