001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package org.objectweb.asm.tree.analysis;
030:
031: import java.util.List;
032:
033: import org.objectweb.asm.Type;
034: import org.objectweb.asm.tree.AbstractInsnNode;
035: import org.objectweb.asm.tree.FieldInsnNode;
036: import org.objectweb.asm.tree.MethodInsnNode;
037:
038: /**
039: * An extended {@link BasicInterpreter} that checks that bytecode instructions
040: * are correctly used.
041: *
042: * @author Eric Bruneton
043: * @author Bing Ran
044: */
045: public class BasicVerifier extends BasicInterpreter {
046:
047: public Value copyOperation(final AbstractInsnNode insn,
048: final Value value) throws AnalyzerException {
049: Value expected;
050: switch (insn.getOpcode()) {
051: case ILOAD:
052: case ISTORE:
053: expected = BasicValue.INT_VALUE;
054: break;
055: case FLOAD:
056: case FSTORE:
057: expected = BasicValue.FLOAT_VALUE;
058: break;
059: case LLOAD:
060: case LSTORE:
061: expected = BasicValue.LONG_VALUE;
062: break;
063: case DLOAD:
064: case DSTORE:
065: expected = BasicValue.DOUBLE_VALUE;
066: break;
067: case ALOAD:
068: if (!((BasicValue) value).isReference()) {
069: throw new AnalyzerException(null,
070: "an object reference", value);
071: }
072: return value;
073: case ASTORE:
074: if (!((BasicValue) value).isReference()
075: && value != BasicValue.RETURNADDRESS_VALUE) {
076: throw new AnalyzerException(null,
077: "an object reference or a return address",
078: value);
079: }
080: return value;
081: default:
082: return value;
083: }
084: // type is necessarily a primitive type here,
085: // so value must be == to expected value
086: if (value != expected) {
087: throw new AnalyzerException(null, expected, value);
088: }
089: return value;
090: }
091:
092: public Value unaryOperation(final AbstractInsnNode insn,
093: final Value value) throws AnalyzerException {
094: Value expected;
095: switch (insn.getOpcode()) {
096: case INEG:
097: case IINC:
098: case I2F:
099: case I2L:
100: case I2D:
101: case I2B:
102: case I2C:
103: case I2S:
104: case IFEQ:
105: case IFNE:
106: case IFLT:
107: case IFGE:
108: case IFGT:
109: case IFLE:
110: case TABLESWITCH:
111: case LOOKUPSWITCH:
112: case IRETURN:
113: case NEWARRAY:
114: case ANEWARRAY:
115: expected = BasicValue.INT_VALUE;
116: break;
117: case FNEG:
118: case F2I:
119: case F2L:
120: case F2D:
121: case FRETURN:
122: expected = BasicValue.FLOAT_VALUE;
123: break;
124: case LNEG:
125: case L2I:
126: case L2F:
127: case L2D:
128: case LRETURN:
129: expected = BasicValue.LONG_VALUE;
130: break;
131: case DNEG:
132: case D2I:
133: case D2F:
134: case D2L:
135: case DRETURN:
136: expected = BasicValue.DOUBLE_VALUE;
137: break;
138: case GETFIELD:
139: expected = newValue(Type.getType("L"
140: + ((FieldInsnNode) insn).owner + ";"));
141: break;
142: case CHECKCAST:
143: if (!((BasicValue) value).isReference()) {
144: throw new AnalyzerException(null,
145: "an object reference", value);
146: }
147: return super .unaryOperation(insn, value);
148: case ARRAYLENGTH:
149: if (!isArrayValue(value)) {
150: throw new AnalyzerException(null, "an array reference",
151: value);
152: }
153: return super .unaryOperation(insn, value);
154: case ARETURN:
155: case ATHROW:
156: case INSTANCEOF:
157: case MONITORENTER:
158: case MONITOREXIT:
159: case IFNULL:
160: case IFNONNULL:
161: if (!((BasicValue) value).isReference()) {
162: throw new AnalyzerException(null,
163: "an object reference", value);
164: }
165: return super .unaryOperation(insn, value);
166: case PUTSTATIC:
167: expected = newValue(Type
168: .getType(((FieldInsnNode) insn).desc));
169: break;
170: default:
171: throw new Error("Internal error.");
172: }
173: if (!isSubTypeOf(value, expected)) {
174: throw new AnalyzerException(null, expected, value);
175: }
176: return super .unaryOperation(insn, value);
177: }
178:
179: public Value binaryOperation(final AbstractInsnNode insn,
180: final Value value1, final Value value2)
181: throws AnalyzerException {
182: Value expected1;
183: Value expected2;
184: switch (insn.getOpcode()) {
185: case IALOAD:
186: expected1 = newValue(Type.getType("[I"));
187: expected2 = BasicValue.INT_VALUE;
188: break;
189: case BALOAD:
190: if (!isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
191: expected1 = newValue(Type.getType("[B"));
192: } else {
193: expected1 = newValue(Type.getType("[Z"));
194: }
195: expected2 = BasicValue.INT_VALUE;
196: break;
197: case CALOAD:
198: expected1 = newValue(Type.getType("[C"));
199: expected2 = BasicValue.INT_VALUE;
200: break;
201: case SALOAD:
202: expected1 = newValue(Type.getType("[S"));
203: expected2 = BasicValue.INT_VALUE;
204: break;
205: case LALOAD:
206: expected1 = newValue(Type.getType("[J"));
207: expected2 = BasicValue.INT_VALUE;
208: break;
209: case FALOAD:
210: expected1 = newValue(Type.getType("[F"));
211: expected2 = BasicValue.INT_VALUE;
212: break;
213: case DALOAD:
214: expected1 = newValue(Type.getType("[D"));
215: expected2 = BasicValue.INT_VALUE;
216: break;
217: case AALOAD:
218: expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
219: expected2 = BasicValue.INT_VALUE;
220: break;
221: case IADD:
222: case ISUB:
223: case IMUL:
224: case IDIV:
225: case IREM:
226: case ISHL:
227: case ISHR:
228: case IUSHR:
229: case IAND:
230: case IOR:
231: case IXOR:
232: case IF_ICMPEQ:
233: case IF_ICMPNE:
234: case IF_ICMPLT:
235: case IF_ICMPGE:
236: case IF_ICMPGT:
237: case IF_ICMPLE:
238: expected1 = BasicValue.INT_VALUE;
239: expected2 = BasicValue.INT_VALUE;
240: break;
241: case FADD:
242: case FSUB:
243: case FMUL:
244: case FDIV:
245: case FREM:
246: case FCMPL:
247: case FCMPG:
248: expected1 = BasicValue.FLOAT_VALUE;
249: expected2 = BasicValue.FLOAT_VALUE;
250: break;
251: case LADD:
252: case LSUB:
253: case LMUL:
254: case LDIV:
255: case LREM:
256: case LAND:
257: case LOR:
258: case LXOR:
259: case LCMP:
260: expected1 = BasicValue.LONG_VALUE;
261: expected2 = BasicValue.LONG_VALUE;
262: break;
263: case LSHL:
264: case LSHR:
265: case LUSHR:
266: expected1 = BasicValue.LONG_VALUE;
267: expected2 = BasicValue.INT_VALUE;
268: break;
269: case DADD:
270: case DSUB:
271: case DMUL:
272: case DDIV:
273: case DREM:
274: case DCMPL:
275: case DCMPG:
276: expected1 = BasicValue.DOUBLE_VALUE;
277: expected2 = BasicValue.DOUBLE_VALUE;
278: break;
279: case IF_ACMPEQ:
280: case IF_ACMPNE:
281: expected1 = BasicValue.REFERENCE_VALUE;
282: expected2 = BasicValue.REFERENCE_VALUE;
283: break;
284: case PUTFIELD:
285: FieldInsnNode fin = (FieldInsnNode) insn;
286: expected1 = newValue(Type.getType("L" + fin.owner + ";"));
287: expected2 = newValue(Type.getType(fin.desc));
288: break;
289: default:
290: throw new Error("Internal error.");
291: }
292: if (!isSubTypeOf(value1, expected1)) {
293: throw new AnalyzerException("First argument", expected1,
294: value1);
295: } else if (!isSubTypeOf(value2, expected2)) {
296: throw new AnalyzerException("Second argument", expected2,
297: value2);
298: }
299: if (insn.getOpcode() == AALOAD) {
300: return getElementValue(value1);
301: } else {
302: return super .binaryOperation(insn, value1, value2);
303: }
304: }
305:
306: public Value ternaryOperation(final AbstractInsnNode insn,
307: final Value value1, final Value value2, final Value value3)
308: throws AnalyzerException {
309: Value expected1;
310: Value expected3;
311: switch (insn.getOpcode()) {
312: case IASTORE:
313: expected1 = newValue(Type.getType("[I"));
314: expected3 = BasicValue.INT_VALUE;
315: break;
316: case BASTORE:
317: if (!isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
318: expected1 = newValue(Type.getType("[B"));
319: } else {
320: expected1 = newValue(Type.getType("[Z"));
321: }
322: expected3 = BasicValue.INT_VALUE;
323: break;
324: case CASTORE:
325: expected1 = newValue(Type.getType("[C"));
326: expected3 = BasicValue.INT_VALUE;
327: break;
328: case SASTORE:
329: expected1 = newValue(Type.getType("[S"));
330: expected3 = BasicValue.INT_VALUE;
331: break;
332: case LASTORE:
333: expected1 = newValue(Type.getType("[J"));
334: expected3 = BasicValue.LONG_VALUE;
335: break;
336: case FASTORE:
337: expected1 = newValue(Type.getType("[F"));
338: expected3 = BasicValue.FLOAT_VALUE;
339: break;
340: case DASTORE:
341: expected1 = newValue(Type.getType("[D"));
342: expected3 = BasicValue.DOUBLE_VALUE;
343: break;
344: case AASTORE:
345: expected1 = value1;
346: expected3 = BasicValue.REFERENCE_VALUE;
347: break;
348: default:
349: throw new Error("Internal error.");
350: }
351: if (!isSubTypeOf(value1, expected1)) {
352: throw new AnalyzerException("First argument", "a "
353: + expected1 + " array reference", value1);
354: } else if (value2 != BasicValue.INT_VALUE) {
355: throw new AnalyzerException("Second argument",
356: BasicValue.INT_VALUE, value2);
357: } else if (!isSubTypeOf(value3, expected3)) {
358: throw new AnalyzerException("Third argument", expected3,
359: value3);
360: }
361: return null;
362: }
363:
364: public Value naryOperation(final AbstractInsnNode insn,
365: final List values) throws AnalyzerException {
366: int opcode = insn.getOpcode();
367: if (opcode == MULTIANEWARRAY) {
368: for (int i = 0; i < values.size(); ++i) {
369: if (values.get(i) != BasicValue.INT_VALUE) {
370: throw new AnalyzerException(null,
371: BasicValue.INT_VALUE, (Value) values.get(i));
372: }
373: }
374: } else {
375: int i = 0;
376: int j = 0;
377: if (opcode != INVOKESTATIC) {
378: String own = ((MethodInsnNode) insn).owner;
379: if (own.charAt(0) != '[') { // can happen with JDK1.5 clone()
380: own = "L" + own + ";";
381: }
382: Type owner = Type.getType(own);
383: if (!isSubTypeOf((Value) values.get(i++),
384: newValue(owner))) {
385: throw new AnalyzerException("Method owner",
386: newValue(owner), (Value) values.get(0));
387: }
388: }
389: Type[] args = Type
390: .getArgumentTypes(((MethodInsnNode) insn).desc);
391: while (i < values.size()) {
392: Value expected = newValue(args[j++]);
393: Value encountered = (Value) values.get(i++);
394: if (!isSubTypeOf(encountered, expected)) {
395: throw new AnalyzerException("Argument " + j,
396: expected, encountered);
397: }
398: }
399: }
400: return super .naryOperation(insn, values);
401: }
402:
403: protected boolean isArrayValue(final Value value) {
404: return ((BasicValue) value).isReference();
405: }
406:
407: protected Value getElementValue(final Value objectArrayValue)
408: throws AnalyzerException {
409: return BasicValue.REFERENCE_VALUE;
410: }
411:
412: protected boolean isSubTypeOf(final Value value,
413: final Value expected) {
414: return value == expected;
415: }
416: }
|