KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > libraries > asm > tree > analysis > BasicVerifier


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000,2002,2003 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31 package oracle.toplink.libraries.asm.tree.analysis;
32
33 import java.util.List JavaDoc;
34
35 import oracle.toplink.libraries.asm.Type;
36 import oracle.toplink.libraries.asm.tree.AbstractInsnNode;
37 import oracle.toplink.libraries.asm.tree.FieldInsnNode;
38 import oracle.toplink.libraries.asm.tree.MethodInsnNode;
39
40 /**
41  * An extended {@link BasicInterpreter} that checks that bytecode instructions
42  * are correctly used.
43  *
44  * @author Eric Bruneton
45  * @author Bing Ran
46  */

47
48 public class BasicVerifier extends BasicInterpreter {
49
50   public Value copyOperation (final AbstractInsnNode insn, final Value value)
51     throws AnalyzerException
52   {
53     Value expected;
54     switch (insn.getOpcode()) {
55       case ILOAD:
56       case ISTORE:
57         expected = BasicValue.INT_VALUE;
58         break;
59       case FLOAD:
60       case FSTORE:
61         expected = BasicValue.FLOAT_VALUE;
62         break;
63       case LLOAD:
64       case LSTORE:
65         expected = BasicValue.LONG_VALUE;
66         break;
67       case DLOAD:
68       case DSTORE:
69         expected = BasicValue.DOUBLE_VALUE;
70         break;
71       case ALOAD:
72         if (!((BasicValue)value).isReference()) {
73           throw new AnalyzerException(null, "an object reference", value);
74         }
75         return value;
76       case ASTORE:
77         if (!((BasicValue)value).isReference() &&
78             value != BasicValue.RETURNADDRESS_VALUE)
79         {
80           throw new AnalyzerException(
81             null, "an object reference or a return address", value);
82         }
83         return value;
84       default:
85         return value;
86     }
87     // type is necessarily a primitive type here,
88
// so value must be == to expected value
89
if (value != expected) {
90       throw new AnalyzerException(null, expected, value);
91     }
92     return value;
93   }
94   
95   public Value unaryOperation (final AbstractInsnNode insn, Value value)
96     throws AnalyzerException
97   {
98     Value expected;
99     switch (insn.getOpcode()) {
100       case INEG:
101       case IINC:
102       case I2F:
103       case I2L:
104       case I2D:
105       case I2B:
106       case I2C:
107       case I2S:
108       case IFEQ:
109       case IFNE:
110       case IFLT:
111       case IFGE:
112       case IFGT:
113       case IFLE:
114       case TABLESWITCH:
115       case LOOKUPSWITCH:
116       case IRETURN:
117       case NEWARRAY:
118       case ANEWARRAY:
119         expected = BasicValue.INT_VALUE;
120         break;
121       case FNEG:
122       case F2I:
123       case F2L:
124       case F2D:
125       case FRETURN:
126         expected = BasicValue.FLOAT_VALUE;
127         break;
128       case LNEG:
129       case L2I:
130       case L2F:
131       case L2D:
132       case LRETURN:
133         expected = BasicValue.LONG_VALUE;
134         break;
135       case DNEG:
136       case D2I:
137       case D2F:
138       case D2L:
139       case DRETURN:
140         expected = BasicValue.DOUBLE_VALUE;
141         break;
142       case GETFIELD:
143         expected = newValue(Type.getType("L" + ((FieldInsnNode)insn).owner + ";"));
144         break;
145       case CHECKCAST:
146         if (!((BasicValue)value).isReference()) {
147           throw new AnalyzerException(null, "an object reference", value);
148         }
149         return super.unaryOperation(insn, value);
150       case ARRAYLENGTH:
151         if (!isArrayValue(value)) {
152           throw new AnalyzerException(null, "an array reference", value);
153         }
154         return super.unaryOperation(insn, value);
155       case ARETURN:
156       case ATHROW:
157       case INSTANCEOF:
158       case MONITORENTER:
159       case MONITOREXIT:
160       case IFNULL:
161       case IFNONNULL:
162         if (!((BasicValue)value).isReference()) {
163           throw new AnalyzerException(null, "an object reference", value);
164         }
165         return super.unaryOperation(insn, value);
166       case PUTSTATIC:
167         expected = newValue(Type.getType(((FieldInsnNode)insn).desc));
168         break;
169       default:
170         throw new RuntimeException JavaDoc("Internal error.");
171     }
172     if (!isSubTypeOf(value, expected)) {
173       throw new AnalyzerException(null, expected, value);
174     }
175     return super.unaryOperation(insn, value);
176   }
177
178   public Value binaryOperation (
179     final AbstractInsnNode insn,
180     final Value value1,
181     final Value value2) throws AnalyzerException
182   {
183     Value expected1;
184     Value expected2;
185     switch (insn.getOpcode()) {
186       case IALOAD:
187       case BALOAD:
188       case CALOAD:
189       case SALOAD:
190         expected1 = newValue(Type.getType("[I"));
191         expected2 = BasicValue.INT_VALUE;
192         break;
193       case LALOAD:
194         expected1 = newValue(Type.getType("[J"));
195         expected2 = BasicValue.INT_VALUE;
196         break;
197       case FALOAD:
198         expected1 = newValue(Type.getType("[F"));
199         expected2 = BasicValue.INT_VALUE;
200         break;
201       case DALOAD:
202         expected1 = newValue(Type.getType("[D"));
203         expected2 = BasicValue.INT_VALUE;
204         break;
205       case AALOAD:
206         expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
207         expected2 = BasicValue.INT_VALUE;
208         break;
209       case IADD:
210       case ISUB:
211       case IMUL:
212       case IDIV:
213       case IREM:
214       case ISHL:
215       case ISHR:
216       case IUSHR:
217       case IAND:
218       case IOR:
219       case IXOR:
220       case IF_ICMPEQ:
221       case IF_ICMPNE:
222       case IF_ICMPLT:
223       case IF_ICMPGE:
224       case IF_ICMPGT:
225       case IF_ICMPLE:
226         expected1 = BasicValue.INT_VALUE;
227         expected2 = BasicValue.INT_VALUE;
228         break;
229       case FADD:
230       case FSUB:
231       case FMUL:
232       case FDIV:
233       case FREM:
234       case FCMPL:
235       case FCMPG:
236         expected1 = BasicValue.FLOAT_VALUE;
237         expected2 = BasicValue.FLOAT_VALUE;
238         break;
239       case LADD:
240       case LSUB:
241       case LMUL:
242       case LDIV:
243       case LREM:
244       case LAND:
245       case LOR:
246       case LXOR:
247       case LCMP:
248         expected1 = BasicValue.LONG_VALUE;
249         expected2 = BasicValue.LONG_VALUE;
250         break;
251       case LSHL:
252       case LSHR:
253       case LUSHR:
254         expected1 = BasicValue.LONG_VALUE;
255         expected2 = BasicValue.INT_VALUE;
256         break;
257       case DADD:
258       case DSUB:
259       case DMUL:
260       case DDIV:
261       case DREM:
262       case DCMPL:
263       case DCMPG:
264         expected1 = BasicValue.DOUBLE_VALUE;
265         expected2 = BasicValue.DOUBLE_VALUE;
266         break;
267       case IF_ACMPEQ:
268       case IF_ACMPNE:
269         expected1 = BasicValue.REFERENCE_VALUE;
270         expected2 = BasicValue.REFERENCE_VALUE;
271         break;
272       case PUTFIELD:
273         FieldInsnNode fin = (FieldInsnNode)insn;
274         expected1 = newValue(Type.getType("L" + fin.owner + ";"));
275         expected2 = newValue(Type.getType(fin.desc));
276         break;
277       default:
278         throw new RuntimeException JavaDoc("Internal error.");
279     }
280     if (!isSubTypeOf(value1, expected1)) {
281       throw new AnalyzerException("First argument", expected1, value1);
282     } else if (!isSubTypeOf(value2, expected2)) {
283       throw new AnalyzerException("Second argument", expected2, value2);
284     }
285     if (insn.getOpcode() == AALOAD) {
286       return getElementValue(value1);
287     } else {
288       return super.binaryOperation(insn, value1, value2);
289     }
290   }
291
292   public Value ternaryOperation (
293     final AbstractInsnNode insn,
294     final Value value1,
295     final Value value2,
296     final Value value3) throws AnalyzerException
297   {
298     Value expected1;
299     Value expected3;
300     switch (insn.getOpcode()) {
301       case IASTORE:
302       case BASTORE:
303       case CASTORE:
304       case SASTORE:
305         expected1 = newValue(Type.getType("[I"));
306         expected3 = BasicValue.INT_VALUE;
307         break;
308       case LASTORE:
309         expected1 = newValue(Type.getType("[J"));
310         expected3 = BasicValue.LONG_VALUE;
311         break;
312       case FASTORE:
313         expected1 = newValue(Type.getType("[F"));
314         expected3 = BasicValue.FLOAT_VALUE;
315         break;
316       case DASTORE:
317         expected1 = newValue(Type.getType("[D"));
318         expected3 = BasicValue.DOUBLE_VALUE;
319         break;
320       case AASTORE:
321         expected1 = value1;
322         expected3 = getElementValue(value1);
323         break;
324       default:
325         throw new RuntimeException JavaDoc("Internal error.");
326     }
327     if (!isSubTypeOf(value1, expected1)) {
328       throw new AnalyzerException(
329         "First argument", "a " + expected1 + " array reference", value1);
330     } else if (value2 != BasicValue.INT_VALUE) {
331       throw new AnalyzerException(
332         "Second argument", BasicValue.INT_VALUE, value2);
333     } else if (!isSubTypeOf(value3, expected3)) {
334       throw new AnalyzerException("Third argument", expected3, value3);
335     }
336     return null;
337   }
338
339   public Value naryOperation (final AbstractInsnNode insn, final List JavaDoc values)
340     throws AnalyzerException
341   {
342     int opcode = insn.getOpcode();
343     if (opcode == MULTIANEWARRAY) {
344       for (int i = 0; i < values.size(); ++i) {
345         if (values.get(i) != BasicValue.INT_VALUE) {
346           throw new AnalyzerException(
347             null, BasicValue.INT_VALUE, (Value)values.get(i));
348         }
349       }
350     } else {
351       int i = 0;
352       int j = 0;
353       if (opcode != INVOKESTATIC) {
354         Type owner = Type.getType("L" + ((MethodInsnNode)insn).owner + ";");
355         if (!isSubTypeOf((Value)values.get(i++), newValue(owner))) {
356           throw new AnalyzerException(
357             "Method owner", newValue(owner), (Value)values.get(0));
358         }
359       }
360       Type[] args = Type.getArgumentTypes(((MethodInsnNode)insn).desc);
361       while (i < values.size()) {
362         Value expected = newValue(args[j++]);
363         Value encountered = (Value)values.get(i++);
364         if (!isSubTypeOf(encountered, expected)) {
365           throw new AnalyzerException("Argument " + j, expected, encountered);
366         }
367       }
368     }
369     return super.naryOperation(insn, values);
370   }
371   
372   protected boolean isArrayValue (final Value value) {
373     return ((BasicValue)value).isReference();
374   }
375   
376   protected Value getElementValue (final Value objectArrayValue)
377     throws AnalyzerException
378   {
379     return BasicValue.REFERENCE_VALUE;
380   }
381     
382   protected boolean isSubTypeOf (final Value value, final Value expected) {
383     return value == expected;
384   }
385 }
386
Popular Tags