001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2003 Ondrej Lhotak
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: package soot.tools;
021:
022: import soot.*;
023: import java.util.*;
024: import soot.jimple.*;
025: import soot.jimple.toolkits.callgraph.*;
026:
027: public class BadFields extends SceneTransformer {
028: public static void main(String[] args) {
029: PackManager.v().getPack("cg").add(
030: new Transform("cg.badfields", new BadFields()));
031: soot.Main.main(args);
032: }
033:
034: private SootClass lastClass;
035: private SootClass currentClass;
036:
037: protected void internalTransform(String phaseName, Map options) {
038: lastClass = null;
039:
040: for (Iterator clIt = Scene.v().getApplicationClasses()
041: .iterator(); clIt.hasNext();) {
042:
043: final SootClass cl = (SootClass) clIt.next();
044: currentClass = cl;
045: handleClass(cl);
046: for (Iterator it = cl.methodIterator(); it.hasNext();) {
047: handleMethod((SootMethod) it.next());
048: }
049: }
050: Scene.v().setCallGraph(new CallGraph());
051: }
052:
053: private void handleClass(SootClass cl) {
054: for (Iterator fIt = cl.getFields().iterator(); fIt.hasNext();) {
055: final SootField f = (SootField) fIt.next();
056: if (!f.isStatic())
057: continue;
058: String typeName = f.getType().toString();
059: if (typeName.equals("java.lang.Class"))
060: continue;
061: if (f.isFinal()) {
062: if (f.getType() instanceof PrimType)
063: continue;
064: if (typeName.equals("java.io.PrintStream"))
065: continue;
066: if (typeName.equals("java.lang.String"))
067: continue;
068: if (typeName.equals("java.lang.Object"))
069: continue;
070: if (typeName.equals("java.lang.Integer"))
071: continue;
072: if (typeName.equals("java.lang.Boolean"))
073: continue;
074: }
075: warn("Bad field " + f);
076: }
077: }
078:
079: private void warn(String warning) {
080: if (lastClass != currentClass)
081: G.v().out.println("In class " + currentClass);
082: lastClass = currentClass;
083: G.v().out.println(" " + warning);
084: }
085:
086: private void handleMethod(SootMethod m) {
087: if (!m.isConcrete())
088: return;
089: for (Iterator bIt = m.retrieveActiveBody().getUseAndDefBoxes()
090: .iterator(); bIt.hasNext();) {
091: final ValueBox b = (ValueBox) bIt.next();
092: Value v = b.getValue();
093: if (!(v instanceof StaticFieldRef))
094: continue;
095: StaticFieldRef sfr = (StaticFieldRef) v;
096: SootField f = sfr.getField();
097: if (!f.getDeclaringClass().getName().equals(
098: "java.lang.System"))
099: continue;
100: if (f.getName().equals("err")) {
101: G.v().out.println("Use of System.err in " + m);
102: }
103: if (f.getName().equals("out")) {
104: G.v().out.println("Use of System.out in " + m);
105: }
106: }
107: for (Iterator sIt = m.getActiveBody().getUnits().iterator(); sIt
108: .hasNext();) {
109: final Stmt s = (Stmt) sIt.next();
110: if (!s.containsInvokeExpr())
111: continue;
112: InvokeExpr ie = s.getInvokeExpr();
113: SootMethod target = ie.getMethod();
114: if (target.getDeclaringClass().getName().equals(
115: "java.lang.System")
116: && target.getName().equals("exit")) {
117: warn("" + m + " calls System.exit");
118: }
119: }
120: if (m.getName().equals("<clinit>")) {
121: for (Iterator sIt = m.getActiveBody().getUnits().iterator(); sIt
122: .hasNext();) {
123: final Stmt s = (Stmt) sIt.next();
124: for (Iterator bIt = s.getUseBoxes().iterator(); bIt
125: .hasNext();) {
126: final ValueBox b = (ValueBox) bIt.next();
127: Value v = b.getValue();
128: if (v instanceof FieldRef) {
129: warn(m.getName() + " reads field " + v);
130: }
131: }
132: if (!s.containsInvokeExpr())
133: continue;
134: InvokeExpr ie = s.getInvokeExpr();
135: SootMethod target = ie.getMethod();
136: calls(target);
137: }
138: }
139: }
140:
141: private void calls(SootMethod target) {
142: if (target.getName().equals("<init>")) {
143: if (target.getDeclaringClass().getName().equals(
144: "java.io.PrintStream"))
145: return;
146: if (target.getDeclaringClass().getName().equals(
147: "java.lang.Boolean"))
148: return;
149: if (target.getDeclaringClass().getName().equals(
150: "java.lang.Integer"))
151: return;
152: if (target.getDeclaringClass().getName().equals(
153: "java.lang.String"))
154: return;
155: if (target.getDeclaringClass().getName().equals(
156: "java.lang.Object"))
157: return;
158: }
159: if (target.getName().equals("getProperty")) {
160: if (target.getDeclaringClass().getName().equals(
161: "java.lang.System"))
162: return;
163: }
164: if (target.getName().equals("charAt")) {
165: if (target.getDeclaringClass().getName().equals(
166: "java.lang.String"))
167: return;
168: }
169: warn("<clinit> invokes " + target);
170: }
171: }
|