/* Soot - a J*va Optimization Framework
* Copyright (C) 2003 Ondrej Lhotak
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package soot.tools;
import soot.*;
import java.util.*;
import soot.jimple.*;
import soot.jimple.toolkits.callgraph.*;
public class BadFields extends SceneTransformer {
public static void main(String[] args)
{
PackManager.v().getPack("cg").add(
new Transform("cg.badfields", new BadFields()));
soot.Main.main(args);
}
private SootClass lastClass;
private SootClass currentClass;
protected void internalTransform(String phaseName, Map options)
{
lastClass = null;
for( Iterator clIt = Scene.v().getApplicationClasses().iterator(); clIt.hasNext(); ) {
final SootClass cl = (SootClass) clIt.next();
currentClass = cl;
handleClass( cl );
for( Iterator it = cl.methodIterator(); it.hasNext(); ) {
handleMethod( (SootMethod) it.next() );
}
}
Scene.v().setCallGraph( new CallGraph() );
}
private void handleClass( SootClass cl ) {
for( Iterator fIt = cl.getFields().iterator(); fIt.hasNext(); ) {
final SootField f = (SootField) fIt.next();
if( !f.isStatic() ) continue;
String typeName = f.getType().toString();
if( typeName.equals( "java.lang.Class" ) ) continue;
if( f.isFinal() ) {
if( f.getType() instanceof PrimType ) continue;
if( typeName.equals( "java.io.PrintStream" ) ) continue;
if( typeName.equals( "java.lang.String" ) ) continue;
if( typeName.equals( "java.lang.Object" ) ) continue;
if( typeName.equals( "java.lang.Integer" ) ) continue;
if( typeName.equals( "java.lang.Boolean" ) ) continue;
}
warn( "Bad field "+f );
}
}
private void warn( String warning ) {
if( lastClass != currentClass )
G.v().out.println( "In class "+currentClass );
lastClass = currentClass;
G.v().out.println( " "+warning );
}
private void handleMethod( SootMethod m ) {
if( !m.isConcrete() ) return;
for( Iterator bIt = m.retrieveActiveBody().getUseAndDefBoxes().iterator(); bIt.hasNext(); ) {
final ValueBox b = (ValueBox) bIt.next();
Value v = b.getValue();
if( !(v instanceof StaticFieldRef) ) continue;
StaticFieldRef sfr = (StaticFieldRef) v;
SootField f = sfr.getField();
if( !f.getDeclaringClass().getName().equals( "java.lang.System" ) )
continue;
if( f.getName().equals( "err" ) ) {
G.v().out.println( "Use of System.err in "+m );
}
if( f.getName().equals( "out" ) ) {
G.v().out.println( "Use of System.out in "+m );
}
}
for( Iterator sIt = m.getActiveBody().getUnits().iterator(); sIt.hasNext(); ) {
final Stmt s = (Stmt) sIt.next();
if( !s.containsInvokeExpr() ) continue;
InvokeExpr ie = s.getInvokeExpr();
SootMethod target = ie.getMethod();
if( target.getDeclaringClass().getName().equals( "java.lang.System" )
&& target.getName().equals( "exit" ) ) {
warn( ""+m+" calls System.exit" );
}
}
if( m.getName().equals( "<clinit>" ) ) {
for( Iterator sIt = m.getActiveBody().getUnits().iterator(); sIt.hasNext(); ) {
final Stmt s = (Stmt) sIt.next();
for( Iterator bIt = s.getUseBoxes().iterator(); bIt.hasNext(); ) {
final ValueBox b = (ValueBox) bIt.next();
Value v = b.getValue();
if( v instanceof FieldRef ) {
warn( m.getName()+" reads field "+v );
}
}
if( !s.containsInvokeExpr() ) continue;
InvokeExpr ie = s.getInvokeExpr();
SootMethod target = ie.getMethod();
calls( target );
}
}
}
private void calls( SootMethod target ) {
if( target.getName().equals("<init>") ) {
if( target.getDeclaringClass().getName().equals( "java.io.PrintStream" ) ) return;
if( target.getDeclaringClass().getName().equals( "java.lang.Boolean" ) ) return;
if( target.getDeclaringClass().getName().equals( "java.lang.Integer" ) ) return;
if( target.getDeclaringClass().getName().equals( "java.lang.String" ) ) return;
if( target.getDeclaringClass().getName().equals( "java.lang.Object" ) ) return;
}
if( target.getName().equals("getProperty") ) {
if( target.getDeclaringClass().getName().equals( "java.lang.System" ) ) return;
}
if( target.getName().equals("charAt") ) {
if( target.getDeclaringClass().getName().equals( "java.lang.String" ) ) return;
}
warn( "<clinit> invokes "+target );
}
}