KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > jimple > toolkits > annotation > arraycheck > ArrayBoundsChecker


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2000 Feng Qian
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 /*
21  * Modified by the Sable Research Group and others 1997-1999.
22  * See the 'credits' file distributed with Soot for the complete list of
23  * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
24  */

25
26 package soot.jimple.toolkits.annotation.arraycheck;
27 import soot.options.*;
28
29 import soot.*;
30 import soot.jimple.*;
31 import soot.toolkits.graph.*;
32 import soot.util.*;
33 import soot.tagkit.*;
34 import soot.jimple.toolkits.annotation.tags.*;
35 import java.util.*;
36 import soot.options.ABCOptions;
37
38 public class ArrayBoundsChecker extends BodyTransformer
39 {
40     public ArrayBoundsChecker( Singletons.Global g ) {}
41     public static ArrayBoundsChecker v() { return G.v().soot_jimple_toolkits_annotation_arraycheck_ArrayBoundsChecker(); }
42
43     protected boolean takeClassField = false;
44     protected boolean takeFieldRef = false;
45     protected boolean takeArrayRef = false;
46     protected boolean takeCSE = false;
47     protected boolean takeRectArray = false;
48     protected boolean addColorTags = false;
49     
50     protected void internalTransform(Body body, String JavaDoc phaseName, Map opts)
51     {
52         ABCOptions options = new ABCOptions( opts );
53         if (options.with_all())
54         {
55             takeClassField = true;
56             takeFieldRef = true;
57             takeArrayRef = true;
58             takeCSE = true;
59             takeRectArray = true;
60         }
61         else
62         {
63             takeClassField = options.with_classfield();
64             takeFieldRef = options.with_fieldref();
65             takeArrayRef = options.with_arrayref();
66             takeCSE = options.with_cse();
67             takeRectArray = options.with_rectarray();
68         }
69
70         addColorTags = options.add_color_tags();
71
72         {
73             SootMethod m = body.getMethod();
74         
75             Date start = new Date();
76
77             if (Options.v().verbose())
78             {
79                 G.v().out.println("[abc] Analyzing array bounds information for "+m.getName());
80                 G.v().out.println("[abc] Started on "+start);
81             }
82
83             ArrayBoundsCheckerAnalysis analysis = null;
84
85             if (hasArrayLocals(body))
86             {
87                 analysis =
88                     new ArrayBoundsCheckerAnalysis(body,
89                                                    takeClassField,
90                                                    takeFieldRef,
91                                                    takeArrayRef,
92                                                    takeCSE,
93                                                    takeRectArray);
94             }
95             
96             SootClass counterClass = null;
97             SootMethod increase = null;
98             
99             if (options.profiling())
100             {
101                 counterClass = Scene.v().loadClassAndSupport("MultiCounter");
102                 increase = counterClass.getMethod("void increase(int)") ;
103             }
104             
105             Chain units = body.getUnits();
106             
107             IntContainer zero = new IntContainer(0);
108             
109             Iterator unitIt = units.snapshotIterator();
110             
111             while (unitIt.hasNext())
112             {
113                 Stmt stmt = (Stmt)unitIt.next();
114        
115                 if (stmt.containsArrayRef())
116                 {
117                     ArrayRef aref = (ArrayRef)stmt.getArrayRef();
118                     
119                     {
120                         WeightedDirectedSparseGraph vgraph =
121                             (WeightedDirectedSparseGraph)analysis.getFlowBefore(stmt);
122             
123                         int res = interpretGraph(vgraph, aref, stmt, zero);
124                         
125                         boolean lowercheck = true;
126                         boolean uppercheck = true;
127                         
128                         if (res == 0) {
129                             lowercheck = true;
130                             uppercheck = true;
131                         }
132                         else if (res == 1) {
133                             lowercheck = true;
134                             uppercheck = false;
135                         }
136                         else if (res == 2) {
137                             lowercheck = false;
138                             uppercheck = true;
139                         }
140                         else if (res == 3) {
141                             lowercheck = false;
142                             uppercheck = false;
143                         }
144                
145                         if (addColorTags){
146                             if (res == 0) {
147                                 aref.getIndexBox().addTag(new ColorTag(255, 0, 0, false, "ArrayCheckTag"));
148                             }
149                             else if (res == 1) {
150                                 aref.getIndexBox().addTag(new ColorTag(255, 248, 35, false, "ArrayCheckTag"));
151                             }
152                             else if (res == 2) {
153                                 aref.getIndexBox().addTag(new ColorTag(255, 163, 0, false, "ArrayCheckTag"));
154                             }
155                             else if (res == 3) {
156                                 aref.getIndexBox().addTag(new ColorTag(45, 255, 84, false, "ArrayCheckTag"));
157                             }
158                             SootClass bodyClass = body.getMethod().getDeclaringClass();
159                             Iterator keysIt = bodyClass.getTags().iterator();
160                             boolean keysAdded = false;
161                             while (keysIt.hasNext()){
162                                 Object JavaDoc next = keysIt.next();
163                                 if (next instanceof KeyTag){
164                                     if (((KeyTag)next).analysisType().equals("ArrayCheckTag")){
165                                         keysAdded = true;
166                                     }
167                                 }
168                             }
169                             if (!keysAdded){
170                                 bodyClass.addTag(new KeyTag(255, 0, 0, "ArrayBounds: Unsafe Lower and Unsafe Upper", "ArrayCheckTag"));
171                                 bodyClass.addTag(new KeyTag(255, 248, 35, "ArrayBounds: Unsafe Lower and Safe Upper", "ArrayCheckTag"));
172                                 bodyClass.addTag(new KeyTag(255, 163, 0, "ArrayBounds: Safe Lower and Unsafe Upper", "ArrayCheckTag"));
173                                 bodyClass.addTag(new KeyTag(45, 255, 84, "ArrayBounds: Safe Lower and Safe Upper", "ArrayCheckTag"));
174                             }
175                         }
176
177                         /*
178                         boolean lowercheck = true;
179                         boolean uppercheck = true;
180                         
181                         {
182                             if (Options.v().debug())
183                             {
184                                 if (!vgraph.makeShortestPathGraph())
185                                 {
186                                     G.v().out.println(stmt+" :");
187                                     G.v().out.println(vgraph);
188                                 }
189                             }
190                             
191                             Value base = aref.getBase();
192                             Value index = aref.getIndex();
193                             
194                             if (index instanceof IntConstant)
195                             {
196                                 int indexv = ((IntConstant)index).value;
197                                 
198                                 if (vgraph.hasEdge(base, zero))
199                                 {
200                                     int alength = vgraph.edgeWeight(base, zero);
201                                     
202                                     if (-alength > indexv)
203                                         uppercheck = false;
204                                 }
205                                 
206                                 if (indexv >= 0)
207                                     lowercheck = false;
208                             }
209                             else
210                             {
211                                 if (vgraph.hasEdge(base, index))
212                                 {
213                                     int upperdistance = vgraph.edgeWeight(base, index);
214                                     if (upperdistance < 0)
215                                         uppercheck = false;
216                                 }
217                                 
218                                 if (vgraph.hasEdge(index, zero))
219                                 {
220                                     int lowerdistance = vgraph.edgeWeight(index, zero);
221
222                                     if (lowerdistance <= 0)
223                                         lowercheck = false;
224                                 }
225                             }
226                         }*/

227                         
228                         if (options.profiling())
229                         {
230                             int lowercounter = 0;
231                             if (!lowercheck)
232                                 lowercounter = 1;
233                             
234                             units.insertBefore (Jimple.v().newInvokeStmt(
235                                  Jimple.v().newStaticInvokeExpr(increase.makeRef(),
236                                         IntConstant.v(lowercounter))), stmt);
237
238                             int uppercounter = 2;
239                             if (!uppercheck)
240                                 uppercounter = 3;
241                             
242                             units.insertBefore (Jimple.v().newInvokeStmt(
243                                  Jimple.v().newStaticInvokeExpr(increase.makeRef(),
244                                         IntConstant.v(uppercounter))), stmt) ;
245
246                             /*
247                             if (!lowercheck && !uppercheck)
248                             {
249                                 units.insertBefore(Jimple.v().newInvokeStmt(
250                                   Jimple.v().newStaticInvokeExpr(increase,
251                                         IntConstant.v(4))), stmt);
252
253                                 NullCheckTag nullTag = (NullCheckTag)stmt.getTag("NullCheckTag");
254                 
255                                 if (nullTag != null && !nullTag.needCheck())
256                                     units.insertBefore(Jimple.v().newInvokeStmt(
257                                         Jimple.v().newStaticInvokeExpr(increase,
258                                             IntConstant.v(7))), stmt);
259                             }
260                             */

261                         }
262                         else
263                         {
264                             Tag checkTag = new ArrayCheckTag(lowercheck, uppercheck);
265                             stmt.addTag(checkTag);
266                         }
267                     }
268                 }
269             }
270
271             if( addColorTags && takeRectArray ) {
272                 RectangularArrayFinder raf = RectangularArrayFinder.v();
273                 for( Iterator vbIt = body.getUseAndDefBoxes().iterator(); vbIt.hasNext(); ) {
274                     final ValueBox vb = (ValueBox) vbIt.next();
275                     Value v = vb.getValue();
276                     if( !(v instanceof Local) ) continue;
277                     Type t = v.getType();
278                     if( !(t instanceof ArrayType) ) continue;
279                     ArrayType at = (ArrayType) t;
280                     if( at.numDimensions <= 1 ) continue;
281                     vb.addTag( new ColorTag(
282                         raf.isRectangular( new MethodLocal(m, (Local) v) )
283                                    ? ColorTag.GREEN
284                                    : ColorTag.RED ));
285                 }
286             }
287
288             Date finish = new Date();
289             if (Options.v().verbose())
290             {
291                 long runtime = finish.getTime() - start.getTime();
292                 G.v().out.println("[abc] ended on "+finish
293                                   +". It took "+(runtime/60000)+" min. "
294                                   +((runtime%60000)/1000)+" sec.");
295             }
296         }
297     }
298
299     private boolean hasArrayLocals(Body body)
300     {
301         Iterator localIt = body.getLocals().iterator();
302         
303         while (localIt.hasNext())
304         {
305             Local local = (Local)localIt.next();
306             if (local.getType() instanceof ArrayType)
307                 return true;
308         }
309         
310         return false;
311     }
312
313     protected int interpretGraph(WeightedDirectedSparseGraph vgraph, ArrayRef aref, Stmt stmt, IntContainer zero){
314     
315         boolean lowercheck = true;
316         boolean uppercheck = true;
317                         
318         {
319             if (Options.v().debug())
320             {
321                 if (!vgraph.makeShortestPathGraph())
322                 {
323                     G.v().out.println(stmt+" :");
324                     G.v().out.println(vgraph);
325                 }
326             }
327                             
328             Value base = aref.getBase();
329             Value index = aref.getIndex();
330                             
331             if (index instanceof IntConstant)
332             {
333                 int indexv = ((IntConstant)index).value;
334                         
335                 if (vgraph.hasEdge(base, zero))
336                 {
337                     int alength = vgraph.edgeWeight(base, zero);
338                                     
339                     if (-alength > indexv)
340                         uppercheck = false;
341                 }
342                                 
343                 if (indexv >= 0)
344                     lowercheck = false;
345             }
346             else
347             {
348                 if (vgraph.hasEdge(base, index))
349                 {
350                     int upperdistance = vgraph.edgeWeight(base, index);
351                     if (upperdistance < 0)
352                         uppercheck = false;
353                 }
354                                 
355                 if (vgraph.hasEdge(index, zero))
356                 {
357                     int lowerdistance = vgraph.edgeWeight(index, zero);
358
359                     if (lowerdistance <= 0)
360                         lowercheck = false;
361                 }
362             }
363         }
364                         
365         
366         if (lowercheck && uppercheck) return 0;
367         else if (lowercheck && !uppercheck) return 1;
368         else if (!lowercheck && uppercheck) return 2;
369         else return 3;
370     }
371 }
372
Popular Tags