KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > asm > tree > analysis > BasicVerifier


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 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 package com.tc.asm.tree.analysis;
31
32 import java.util.List JavaDoc;
33
34 import com.tc.asm.Type;
35 import com.tc.asm.tree.AbstractInsnNode;
36 import com.tc.asm.tree.FieldInsnNode;
37 import com.tc.asm.tree.MethodInsnNode;
38
39 /**
40  * An extended {@link BasicInterpreter} that checks that bytecode instructions
41  * are correctly used.
42  *
43  * @author Eric Bruneton
44  * @author Bing Ran
45  */

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