View Javadoc

1   package joeq.Compiler.Analysis.IPSSA.Apps;
2   
3   import java.util.Arrays;
4   import java.util.Collection;
5   import java.util.Collections;
6   import java.util.HashSet;
7   import java.util.Iterator;
8   import java.util.LinkedList;
9   import java.util.Set;
10  import java.io.BufferedReader;
11  import java.io.FileReader;
12  import java.io.IOException;
13  import joeq.Class.PrimordialClassLoader;
14  import joeq.Class.jq_Class;
15  import joeq.Class.jq_Field;
16  import joeq.Class.jq_Method;
17  import joeq.Class.jq_Type;
18  import joeq.Compiler.Analysis.IPA.PAResultSelector;
19  import joeq.Compiler.Analysis.IPSSA.IPSSABuilder;
20  import joeq.Compiler.Quad.CallGraph;
21  import joeq.Compiler.Quad.RootedCHACallGraph;
22  import joeq.Main.HostedVM;
23  import jwutil.collections.AppendIterator;
24  import jwutil.util.Assert;
25  
26  public class FindBadStores extends IPSSABuilder.Application {    
27      private static CallGraph _cg         = null;
28      private Set _classes                                  = null;
29      
30      // filter out non-local classes?
31      static final boolean FILTER_LOCAL          = false;
32      static jq_Class  _serializableClass  = null;
33      private jq_Class _httpSessionClass   = null;
34      private PAResultSelector _sel; 
35      
36  
37      FindBadStores(IPSSABuilder builder, String name, String[] args) {
38          super(builder, name, args);
39      }    
40      
41      protected void parseParams(String[] argv) {
42          // TODO    
43      }
44      
45      public static void main(String[] args) {
46          HostedVM.initialize();
47          
48          Iterator i = null;
49          for (int x=0; x<args.length; ++x) {
50              if (args[x].equals("-file")) {
51                  try {
52                      BufferedReader br = new BufferedReader(new FileReader(args[++x]));
53                      LinkedList list = new LinkedList();
54                      for (;;) {
55                          String s = br.readLine();
56                          if (s == null) break;
57                          if (s.length() == 0) continue;
58                          if (s.startsWith("%")) continue;
59                          if (s.startsWith("#")) continue;
60                          list.add(s);
61                      }
62                      i = new AppendIterator(list.iterator(), i);
63                  }catch(IOException e) {
64                      e.printStackTrace();
65                      System.exit(2);
66                  }
67                  
68              } else
69              if (args[x].endsWith("*")) {
70                  i = new AppendIterator(PrimordialClassLoader.loader.listPackage(args[x].substring(0, args[x].length()-1)), i);
71              } else 
72              if(args[x].charAt(0) == '-'){
73                  System.exit(2);                    
74              }else {
75                  String classname = args[x];
76                  i = new AppendIterator(Collections.singleton(classname).iterator(), i);
77              }
78          }
79  
80          FindBadStores finder = new FindBadStores(i);
81          finder.run();
82      }
83      
84      public FindBadStores(Iterator i) {
85          Collection roots = new LinkedList();
86          Collection root_classes = new LinkedList();
87          while(i.hasNext()) {
88              jq_Class c = (jq_Class) jq_Type.parseType((String)i.next());
89              c.load();
90              root_classes.add(c);
91  
92              roots.addAll(Arrays.asList(c.getDeclaredStaticMethods()));
93          }
94          
95          //System.out.println("Classes: " + classes);
96          System.out.println("Roots: " + roots);
97          
98          System.out.print("Building call graph...");
99          long time = System.currentTimeMillis();
100         _cg = new RootedCHACallGraph();
101         _cg.setRoots(roots);
102         //_cg = new CachedCallGraph(_cg);
103         
104         time = System.currentTimeMillis() - time;
105         System.out.println("done. ("+(time/1000.)+" seconds)");
106         _classes = getClasses(_cg.getAllMethods());
107         //if(FILTER_LOCAL) _classes = filter(_classes, root_classes);
108         
109         if(FILTER_LOCAL){
110             System.out.println("Considering classes: " + _classes);
111         }        
112         
113         ////
114         _serializableClass = (jq_Class)jq_Type.parseType("Ljava.io.Serializable");
115         Assert._assert(_serializableClass != null);
116         _serializableClass.prepare();
117         ////
118         _httpSessionClass  = (jq_Class)jq_Type.parseType("Ljavax.servlet.HttpSession");        
119         Assert._assert(_httpSessionClass != null);
120         _httpSessionClass.prepare();
121         
122         _sel = new PAResultSelector(_builder.getPAResults());
123     }
124 
125     private Set getClasses(Collection collection) {
126         HashSet result = new HashSet(); 
127         for(Iterator iter = collection.iterator(); iter.hasNext(); ) {
128             jq_Method method = (jq_Method)iter.next();
129             //System.err.println("Saw " + method);
130          
131             jq_Class c = method.getDeclaringClass();
132             if(c != null) {
133                 result.add(c);
134             }
135         }
136         
137         return result;
138     }
139     
140     private void processClasses() {      
141         for(Iterator iter = _classes.iterator(); iter.hasNext(); ) {
142             jq_Class c = (jq_Class)iter.next();
143             
144             if(!c.isSubtypeOf(_httpSessionClass)) continue;
145             
146             System.out.println("Looking at " + c);
147             jq_Field[] instanceFields = c.getDeclaredInstanceFields();
148             jq_Field[] staticFields = c.getStaticFields();
149             
150             processFields(c, instanceFields);
151             processFields(c, staticFields);
152         }        
153     }
154     
155     /***
156      * @param c
157      * @param fields
158      */
159     private void processFields(jq_Class c, jq_Field[] fields) {
160         for(int i = 0; i < fields.length; i++){
161             jq_Field f = fields[i];
162             
163             processField(c, f);
164         }
165     }
166 
167     /***
168      * @param c
169      * @param f
170      */
171     private void processField(jq_Class c, jq_Field f){
172         //         1. find heap objects it can point to
173         //         2. get their types
174         Set types = _sel.getFieldPointeeTypes(f);
175         //  3. figure out which ones are *not* serializable
176         for(Iterator typeIter = types.iterator(); typeIter.hasNext();){
177             jq_Type type = (jq_Type) typeIter.next();
178             if(!(type instanceof jq_Class)){
179                 // skip basic types
180                 continue;
181             }
182             
183             jq_Class typeClass = (jq_Class) type;
184             if(typeClass.getDeclaredInterface(_serializableClass.getDesc()) == null){
185                 System.err.println(c + "." + f + "\ttype " + c + " is not serializable");
186             }
187         }
188     }
189 
190     public void run(){        
191         processClasses();
192     }
193 }