All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.wala.analysis.exceptionanalysis.ExceptionAnalysis Maven / Gradle / Ivy

/*
 * 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.analysis.arraybounds.ArrayOutOfBoundsAnalysis;
import com.ibm.wala.analysis.nullpointer.IntraproceduralNullPointerAnalysis;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.dataflow.graph.BitVectorFramework;
import com.ibm.wala.dataflow.graph.BitVectorSolver;
import com.ibm.wala.fixpoint.BitVectorVariable;
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.SSAInstruction.Visitor;
import com.ibm.wala.ssa.SSAInvokeInstruction;
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;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;

/**
 * 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 {@code } */ public class ExceptionAnalysis { private final BitVectorSolver solver; private final Exception2BitvectorTransformer transformer; private final InterproceduralExceptionFilter filter; private final ClassHierarchy cha; private final CGIntraproceduralExceptionAnalysis intraResult; private final CallGraph cg; private boolean isSolved = false; public ExceptionAnalysis( CallGraph callgraph, PointerAnalysis pointerAnalysis, ClassHierarchy cha) { this(callgraph, pointerAnalysis, cha, null); } /** * @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 pointerAnalysis, ClassHierarchy cha, InterproceduralExceptionFilter filter) { this.cha = cha; this.cg = callgraph; this.filter = Objects.requireNonNullElseGet( filter, () -> new IgnoreExceptionsInterFilter<>(new DummyFilter<>())); intraResult = new CGIntraproceduralExceptionAnalysis(callgraph, pointerAnalysis, cha, this.filter); transformer = new Exception2BitvectorTransformer(intraResult.getExceptions()); ExceptionTransferFunctionProvider transferFunctionProvider = new ExceptionTransferFunctionProvider(intraResult, callgraph, transformer); Graph graph = new InvertedGraph<>(callgraph); BitVectorFramework problem = new BitVectorFramework<>(graph, transferFunctionProvider, transformer.getValues()); solver = new InitializedBitVectorSolver(problem); solver.initForFirstSolve(); } public void solve() { try { solver.solve(null); } catch (CancelException 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 caughtExceptions = catchBlock.getCaughtExceptionTypes(); Set thrownExceptions = this.getExceptions(node, instruction); boolean isCaught = false; while (caughtExceptions.hasNext() && !isCaught) { TypeReference caughtException = caughtExceptions.next(); IClass caughtExceptionClass = cha.lookupClass(caughtException); if (caughtExceptionClass == null) { // for now, assume it is not caught continue; } for (TypeReference thrownException : thrownExceptions) { IClass thrownExceptionClass = cha.lookupClass(thrownException); if (thrownExceptionClass == null) { // for now, assume it is not caught continue; } isCaught |= cha.isAssignableFrom(caughtExceptionClass, thrownExceptionClass); if (isCaught) break; } } return isCaught; } else { return false; } } /** * @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 exceptions = this.getExceptions(node, instruction); boolean allCaught = true; for (TypeReference thrownException : exceptions) { boolean isCaught = false; for (ISSABasicBlock catchBlock : node.getIR().getControlFlowGraph().getExceptionalSuccessors(block)) { Iterator 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. * * @return all exceptions, which may be raised by this instruction */ public Set getExceptions(final CGNode node, SSAInstruction instruction) { if (!isSolved) { throw new IllegalStateException("You need to use .solve() first!"); } final Set thrown = intraResult.getAnalysis(node).collectThrownExceptions(instruction); instruction.visit( new Visitor() { @Override public void visitInvoke(SSAInvokeInstruction instruction) { CallSiteReference site = instruction.getCallSite(); Set targets = cg.getPossibleTargets(node, site); for (CGNode target : targets) { thrown.addAll(getCGNodeExceptions(target)); } } }); Set result = thrown; if (filter != null) { ExceptionFilter nodeFilter = filter.getFilter(node); result = ExceptionMatcher.retainedExceptions( thrown, nodeFilter.filteredExceptions(instruction), cha); } return result; } /** * @return all exceptions, which might be thrown by the method represented through the call graph * node. */ public Set 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); } else { return null; } } /** * @return the used filter */ public InterproceduralExceptionFilter getFilter() { if (!isSolved) { throw new IllegalStateException("You need to use .solve() first!"); } return filter; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy