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
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
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
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
103
104 time = System.currentTimeMillis() - time;
105 System.out.println("done. ("+(time/1000.)+" seconds)");
106 _classes = getClasses(_cg.getAllMethods());
107
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
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
173
174 Set types = _sel.getFieldPointeeTypes(f);
175
176 for(Iterator typeIter = types.iterator(); typeIter.hasNext();){
177 jq_Type type = (jq_Type) typeIter.next();
178 if(!(type instanceof jq_Class)){
179
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 }