KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > jimple > toolkits > base > ExceptionChecker


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2004 Jennifer Lhotak
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */

19
20 package soot.jimple.toolkits.base;
21
22 import soot.*;
23 import soot.jimple.*;
24 import soot.util.*;
25 import java.util.*;
26 import soot.jimple.toolkits.scalar.*;
27 import soot.tagkit.*;
28
29 public class ExceptionChecker extends BodyTransformer{
30
31     FastHierarchy hierarchy;
32     ExceptionCheckerErrorReporter reporter;
33
34     public ExceptionChecker(ExceptionCheckerErrorReporter r){
35         this.reporter = r;
36     }
37
38     protected void internalTransform(Body b, String JavaDoc phaseName, Map options){
39
40         Iterator it = b.getUnits().iterator();
41         while (it.hasNext()){
42             Stmt s = (Stmt)it.next();
43             if (s instanceof ThrowStmt){
44                 ThrowStmt ts = (ThrowStmt)s;
45                 checkThrow(b, ts);
46             }
47             else if (s instanceof InvokeStmt){
48                 InvokeStmt is = (InvokeStmt)s;
49                 checkInvoke(b, is);
50             }
51             else if ((s instanceof AssignStmt) && (((AssignStmt)s).getRightOp() instanceof InvokeExpr)){
52                 InvokeExpr ie = (InvokeExpr)((AssignStmt)s).getRightOp();
53                 checkInvokeExpr(b, ie, s);
54             }
55         }
56     }
57
58     protected void checkThrow(Body b, ThrowStmt ts){
59         if (isThrowDeclared(b, ((RefType)ts.getOp().getType()).getSootClass()) || isThrowFromCompiler(ts) || isExceptionCaught(b, ts, (RefType)ts.getOp().getType())) return;
60         if (reporter != null){
61             reporter.reportError(new ExceptionCheckerError(b.getMethod(), ((RefType)ts.getOp().getType()).getSootClass(), ts, (SourceLnPosTag)ts.getOpBox().getTag("SourceLnPosTag")));
62         }
63     }
64
65     // does the method declare the throw if its a throw that needs declaring
66
// RuntimeException and subclasses do not need to be declared
67
// Error and subclasses do not need to be declared
68
protected boolean isThrowDeclared(Body b, SootClass throwClass){
69         if (hierarchy == null){
70             hierarchy = new FastHierarchy();
71         }
72
73         // handles case when exception is RuntimeException or Error
74
if (throwClass.equals(Scene.v().getSootClass("java.lang.RuntimeException")) || throwClass.equals(Scene.v().getSootClass("java.lang.Error"))) return true;
75         // handles case when exception is a subclass of RuntimeException or Error
76
if (hierarchy.isSubclass(throwClass, Scene.v().getSootClass("java.lang.RuntimeException")) || hierarchy.isSubclass(throwClass, Scene.v().getSootClass("java.lang.Error"))) return true;
77
78         // handles case when exact exception is thrown
79
if (b.getMethod().throwsException(throwClass)) return true;
80
81         // handles case when a super type of the exception is thrown
82
Iterator it = b.getMethod().getExceptions().iterator();
83         while (it.hasNext()){
84             SootClass nextEx = (SootClass)it.next();
85             if (hierarchy.isSubclass(throwClass, nextEx)) return true;
86         }
87         return false;
88     }
89
90     // is the throw created by the compiler
91
protected boolean isThrowFromCompiler(ThrowStmt ts){
92         if (ts.hasTag("ThrowCreatedByCompilerTag")) return true;
93         return false;
94     }
95
96     // is the throw caught inside the method
97
protected boolean isExceptionCaught(Body b, Stmt s, RefType throwType){
98         if (hierarchy == null){
99             hierarchy = new FastHierarchy();
100         }
101         Iterator it = b.getTraps().iterator();
102         while (it.hasNext()){
103             Trap trap = (Trap)it.next();
104             if (trap.getException().getType().equals(throwType) || hierarchy.isSubclass(throwType.getSootClass(), ((RefType)trap.getException().getType()).getSootClass())){
105                 if (isThrowInStmtRange(b, (Stmt)trap.getBeginUnit(), (Stmt)trap.getEndUnit(), s)) return true;
106             }
107         }
108         return false;
109     }
110
111     protected boolean isThrowInStmtRange(Body b, Stmt begin, Stmt end, Stmt s){
112         Iterator it = b.getUnits().iterator(begin, end);
113         while (it.hasNext()){
114             if (it.next().equals(s)) return true;
115         }
116         return false;
117     }
118
119     protected void checkInvoke(Body b, InvokeStmt is){
120         checkInvokeExpr(b, is.getInvokeExpr(), is);
121     }
122
123     // Given a method signature, see if it is declared in the given interface.
124
// If so, return the exceptions thrown by the declaration. Otherwise,
125
// Do the same thing recursively on superinterfaces and Object
126
// and return the intersection. This gives
127
// the maximal set of exceptions that could be declared to be thrown if the
128
// interface had declared the method. Returns null if no supertype declares
129
// the method.
130
private List getExceptionSpec(SootClass intrface,NumberedString sig) {
131         if(intrface.declaresMethod(sig)) return intrface.getMethod(sig).getExceptions();
132         List result=null;
133         SootClass obj=Scene.v().getSootClass("java.lang.Object");
134         if(obj.declaresMethod(sig)) result=new Vector(obj.getMethod(sig).getExceptions());
135         Iterator intrfacesit=intrface.getInterfaces().iterator();
136         while(intrfacesit.hasNext()) {
137             SootClass suprintr=(SootClass) intrfacesit.next();
138             List other=getExceptionSpec(suprintr,sig);
139             if(other!=null)
140                 if(result==null) result=other;
141                 else result.retainAll(other);
142         }
143         return result;
144     }
145
146
147     protected void checkInvokeExpr(Body b, InvokeExpr ie, Stmt s){
148         if(ie instanceof InstanceInvokeExpr &&
149            ((InstanceInvokeExpr) ie).getBase().getType() instanceof ArrayType &&
150            ie.getMethodRef().name().equals("clone") &&
151            ie.getMethodRef().parameterTypes().size()==0)
152             return; // the call is to the clone() method of an array type, which
153
// is defined not to throw any exceptions; if we left this to
154
// normal resolution we'd get the method in Object which does
155
// throw CloneNotSupportedException
156

157         List exceptions=ie instanceof InterfaceInvokeExpr
158             // For an invokeinterface, there is no unique resolution for the
159
// method reference that will get the "correct" exception spec. We
160
// actually need to look at the intersection of all declarations of
161
// the method in supertypes.
162
? getExceptionSpec(ie.getMethodRef().declaringClass(),
163                                ie.getMethodRef().getSubSignature())
164             // Otherwise, we just do normal resolution.
165
: ie.getMethod().getExceptions();
166         Iterator it = exceptions.iterator();
167         while (it.hasNext()){
168             SootClass sc = (SootClass)it.next();
169             if (isThrowDeclared(b, sc) || isExceptionCaught(b, s, sc.getType())) continue;
170             if (reporter != null){
171                 if (s instanceof InvokeStmt){
172                     reporter.reportError(new ExceptionCheckerError(b.getMethod(), sc, s, (SourceLnPosTag)s.getTag("SourceLnPosTag")));
173                 }
174                 else if (s instanceof AssignStmt){
175                     reporter.reportError(new ExceptionCheckerError(b.getMethod(), sc, s, (SourceLnPosTag)((AssignStmt)s).getRightOpBox().getTag("SourceLnPosTag")));
176                 }
177             }
178         }
179     }
180 }
181
Popular Tags