KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > 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 org.objectweb.asm.tree.analysis;
31
32 import java.util.List JavaDoc;
33
34 import org.objectweb.asm.Type;
35 import org.objectweb.asm.tree.AbstractInsnNode;
36 import org.objectweb.asm.tree.FieldInsnNode;
37 import org.objectweb.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             case BALOAD:
196             case CALOAD:
197             case SALOAD:
198                 expected1 = newValue(Type.getType("[I"));
199                 expected2 = BasicValue.INT_VALUE;
200                 break;
201             case LALOAD:
202                 expected1 = newValue(Type.getType("[J"));
203                 expected2 = BasicValue.INT_VALUE;
204                 break;
205             case FALOAD:
206                 expected1 = newValue(Type.getType("[F"));
207                 expected2 = BasicValue.INT_VALUE;
208                 break;
209             case DALOAD:
210                 expected1 = newValue(Type.getType("[D"));
211                 expected2 = BasicValue.INT_VALUE;
212                 break;
213             case AALOAD:
214                 expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
215                 expected2 = BasicValue.INT_VALUE;
216                 break;
217             case IADD:
218             case ISUB:
219             case IMUL:
220             case IDIV:
221             case IREM:
222             case ISHL:
223             case ISHR:
224             case IUSHR:
225             case IAND:
226             case IOR:
227             case IXOR:
228             case IF_ICMPEQ:
229             case IF_ICMPNE:
230             case IF_ICMPLT:
231             case IF_ICMPGE:
232             case IF_ICMPGT:
233             case IF_ICMPLE:
234                 expected1 = BasicValue.INT_VALUE;
235                 expected2 = BasicValue.INT_VALUE;
236                 break;
237             case FADD:
238             case FSUB:
239             case FMUL:
240             case FDIV:
241             case FREM:
242             case FCMPL:
243             case FCMPG:
244                 expected1 = BasicValue.FLOAT_VALUE;
245                 expected2 = BasicValue.FLOAT_VALUE;
246                 break;
247             case LADD:
248             case LSUB:
249             case LMUL:
250             case LDIV:
251             case LREM:
252             case LAND:
253             case LOR:
254             case LXOR:
255             case LCMP:
256                 expected1 = BasicValue.LONG_VALUE;
257                 expected2 = BasicValue.LONG_VALUE;
258                 break;
259             case LSHL:
260             case LSHR:
261             case LUSHR:
262                 expected1 = BasicValue.LONG_VALUE;
263                 expected2 = BasicValue.INT_VALUE;
264                 break;
265             case DADD:
266             case DSUB:
267             case DMUL:
268             case DDIV:
269             case DREM:
270             case DCMPL:
271             case DCMPG:
272                 expected1 = BasicValue.DOUBLE_VALUE;
273                 expected2 = BasicValue.DOUBLE_VALUE;
274                 break;
275             case IF_ACMPEQ:
276             case IF_ACMPNE:
277                 expected1 = BasicValue.REFERENCE_VALUE;
278                 expected2 = BasicValue.REFERENCE_VALUE;
279                 break;
280             case PUTFIELD:
281                 FieldInsnNode fin = (FieldInsnNode) insn;
282                 expected1 = newValue(Type.getType("L" + fin.owner + ";"));
283                 expected2 = newValue(Type.getType(fin.desc));
284                 break;
285             default:
286                 throw new RuntimeException JavaDoc("Internal error.");
287         }
288         if (!isSubTypeOf(value1, expected1)) {
289             throw new AnalyzerException("First argument", expected1, value1);
290         } else if (!isSubTypeOf(value2, expected2)) {
291             throw new AnalyzerException("Second argument", expected2, value2);
292         }
293         if (insn.getOpcode() == AALOAD) {
294             return getElementValue(value1);
295         } else {
296             return super.binaryOperation(insn, value1, value2);
297         }
298     }
299
300     public Value ternaryOperation(
301         final AbstractInsnNode insn,
302         final Value value1,
303         final Value value2,
304         final Value value3) throws AnalyzerException
305     {
306         Value expected1;
307         Value expected3;
308         switch (insn.getOpcode()) {
309             case IASTORE:
310             case BASTORE:
311             case CASTORE:
312             case SASTORE:
313                 expected1 = newValue(Type.getType("[I"));
314                 expected3 = BasicValue.INT_VALUE;
315                 break;
316             case LASTORE:
317                 expected1 = newValue(Type.getType("[J"));
318                 expected3 = BasicValue.LONG_VALUE;
319                 break;
320             case FASTORE:
321                 expected1 = newValue(Type.getType("[F"));
322                 expected3 = BasicValue.FLOAT_VALUE;
323                 break;
324             case DASTORE:
325                 expected1 = newValue(Type.getType("[D"));
326                 expected3 = BasicValue.DOUBLE_VALUE;
327                 break;
328             case AASTORE:
329                 expected1 = value1;
330                 expected3 = BasicValue.REFERENCE_VALUE;
331                 break;
332             default:
333                 throw new RuntimeException JavaDoc("Internal error.");
334         }
335         if (!isSubTypeOf(value1, expected1)) {
336             throw new AnalyzerException("First argument", "a " + expected1
337                     + " array reference", value1);
338         } else if (value2 != BasicValue.INT_VALUE) {
339             throw new AnalyzerException("Second argument",
340                     BasicValue.INT_VALUE,
341                     value2);
342         } else if (!isSubTypeOf(value3, expected3)) {
343             throw new AnalyzerException("Third argument", expected3, value3);
344         }
345         return null;
346     }
347
348     public Value naryOperation(final AbstractInsnNode insn, final List JavaDoc values)
349             throws AnalyzerException
350     {
351         int opcode = insn.getOpcode();
352         if (opcode == MULTIANEWARRAY) {
353             for (int i = 0; i < values.size(); ++i) {
354                 if (values.get(i) != BasicValue.INT_VALUE) {
355                     throw new AnalyzerException(null,
356                             BasicValue.INT_VALUE,
357                             (Value) values.get(i));
358                 }
359             }
360         } else {
361             int i = 0;
362             int j = 0;
363             if (opcode != INVOKESTATIC) {
364                 String JavaDoc own = ((MethodInsnNode) insn).owner;
365                 if (own.charAt(0) != '[') { // can happen with JDK1.5 clone()
366
own = "L" + own + ";";
367                 }
368                 Type owner = Type.getType(own);
369                 if (!isSubTypeOf((Value) values.get(i++), newValue(owner))) {
370                     throw new AnalyzerException("Method owner",
371                             newValue(owner),
372                             (Value) values.get(0));
373                 }
374             }
375             Type[] args = Type.getArgumentTypes(((MethodInsnNode) insn).desc);
376             while (i < values.size()) {
377                 Value expected = newValue(args[j++]);
378                 Value encountered = (Value) values.get(i++);
379                 if (!isSubTypeOf(encountered, expected)) {
380                     throw new AnalyzerException("Argument " + j,
381                             expected,
382                             encountered);
383                 }
384             }
385         }
386         return super.naryOperation(insn, values);
387     }
388
389     protected boolean isArrayValue(final Value value) {
390         return ((BasicValue) value).isReference();
391     }
392
393     protected Value getElementValue(final Value objectArrayValue)
394             throws AnalyzerException
395     {
396         return BasicValue.REFERENCE_VALUE;
397     }
398
399     protected boolean isSubTypeOf(final Value value, final Value expected) {
400         return value == expected;
401     }
402 }
403
Popular Tags