~ubuntu-branches/ubuntu/vivid/libasm4-java/vivid

1 by Damien Raude-Morvan
Import upstream version 4.1
1
/***
2
 * ASM: a very small and fast Java bytecode manipulation framework
3
 * Copyright (c) 2000-2011 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;
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.InvokeDynamicInsnNode;
38
import org.objectweb.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
public class BasicVerifier extends BasicInterpreter {
48
49
    public BasicVerifier() {
1.1.2 by Emmanuel Bourg
Import upstream version 5.0.1
50
        super(ASM5);
1 by Damien Raude-Morvan
Import upstream version 4.1
51
    }
52
53
    protected BasicVerifier(final int api) {
54
        super(api);
55
    }
56
57
    @Override
58
    public BasicValue copyOperation(final AbstractInsnNode insn,
59
            final BasicValue value) throws AnalyzerException {
60
        Value expected;
61
        switch (insn.getOpcode()) {
62
        case ILOAD:
63
        case ISTORE:
64
            expected = BasicValue.INT_VALUE;
65
            break;
66
        case FLOAD:
67
        case FSTORE:
68
            expected = BasicValue.FLOAT_VALUE;
69
            break;
70
        case LLOAD:
71
        case LSTORE:
72
            expected = BasicValue.LONG_VALUE;
73
            break;
74
        case DLOAD:
75
        case DSTORE:
76
            expected = BasicValue.DOUBLE_VALUE;
77
            break;
78
        case ALOAD:
79
            if (!value.isReference()) {
80
                throw new AnalyzerException(insn, null, "an object reference",
81
                        value);
82
            }
83
            return value;
84
        case ASTORE:
85
            if (!value.isReference()
86
                    && !BasicValue.RETURNADDRESS_VALUE.equals(value)) {
87
                throw new AnalyzerException(insn, null,
88
                        "an object reference or a return address", value);
89
            }
90
            return value;
91
        default:
92
            return value;
93
        }
94
        if (!expected.equals(value)) {
95
            throw new AnalyzerException(insn, null, expected, value);
96
        }
97
        return value;
98
    }
99
100
    @Override
101
    public BasicValue unaryOperation(final AbstractInsnNode insn,
102
            final BasicValue value) throws AnalyzerException {
103
        BasicValue expected;
104
        switch (insn.getOpcode()) {
105
        case INEG:
106
        case IINC:
107
        case I2F:
108
        case I2L:
109
        case I2D:
110
        case I2B:
111
        case I2C:
112
        case I2S:
113
        case IFEQ:
114
        case IFNE:
115
        case IFLT:
116
        case IFGE:
117
        case IFGT:
118
        case IFLE:
119
        case TABLESWITCH:
120
        case LOOKUPSWITCH:
121
        case IRETURN:
122
        case NEWARRAY:
123
        case ANEWARRAY:
124
            expected = BasicValue.INT_VALUE;
125
            break;
126
        case FNEG:
127
        case F2I:
128
        case F2L:
129
        case F2D:
130
        case FRETURN:
131
            expected = BasicValue.FLOAT_VALUE;
132
            break;
133
        case LNEG:
134
        case L2I:
135
        case L2F:
136
        case L2D:
137
        case LRETURN:
138
            expected = BasicValue.LONG_VALUE;
139
            break;
140
        case DNEG:
141
        case D2I:
142
        case D2F:
143
        case D2L:
144
        case DRETURN:
145
            expected = BasicValue.DOUBLE_VALUE;
146
            break;
147
        case GETFIELD:
148
            expected = newValue(Type
149
                    .getObjectType(((FieldInsnNode) insn).owner));
150
            break;
151
        case CHECKCAST:
152
            if (!value.isReference()) {
153
                throw new AnalyzerException(insn, null, "an object reference",
154
                        value);
155
            }
156
            return super.unaryOperation(insn, value);
157
        case ARRAYLENGTH:
158
            if (!isArrayValue(value)) {
159
                throw new AnalyzerException(insn, null, "an array reference",
160
                        value);
161
            }
162
            return super.unaryOperation(insn, value);
163
        case ARETURN:
164
        case ATHROW:
165
        case INSTANCEOF:
166
        case MONITORENTER:
167
        case MONITOREXIT:
168
        case IFNULL:
169
        case IFNONNULL:
170
            if (!value.isReference()) {
171
                throw new AnalyzerException(insn, null, "an object reference",
172
                        value);
173
            }
174
            return super.unaryOperation(insn, value);
175
        case PUTSTATIC:
176
            expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
177
            break;
178
        default:
179
            throw new Error("Internal error.");
180
        }
181
        if (!isSubTypeOf(value, expected)) {
182
            throw new AnalyzerException(insn, null, expected, value);
183
        }
184
        return super.unaryOperation(insn, value);
185
    }
186
187
    @Override
188
    public BasicValue binaryOperation(final AbstractInsnNode insn,
189
            final BasicValue value1, final BasicValue value2)
190
            throws AnalyzerException {
191
        BasicValue expected1;
192
        BasicValue 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("[Z"));
201
            } else {
202
                expected1 = newValue(Type.getType("[B"));
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.getObjectType(fin.owner));
296
            expected2 = newValue(Type.getType(fin.desc));
297
            break;
298
        default:
299
            throw new Error("Internal error.");
300
        }
301
        if (!isSubTypeOf(value1, expected1)) {
302
            throw new AnalyzerException(insn, "First argument", expected1,
303
                    value1);
304
        } else if (!isSubTypeOf(value2, expected2)) {
305
            throw new AnalyzerException(insn, "Second argument", expected2,
306
                    value2);
307
        }
308
        if (insn.getOpcode() == AALOAD) {
309
            return getElementValue(value1);
310
        } else {
311
            return super.binaryOperation(insn, value1, value2);
312
        }
313
    }
314
315
    @Override
316
    public BasicValue ternaryOperation(final AbstractInsnNode insn,
317
            final BasicValue value1, final BasicValue value2,
318
            final BasicValue value3) throws AnalyzerException {
319
        BasicValue expected1;
320
        BasicValue 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("[Z"));
329
            } else {
330
                expected1 = newValue(Type.getType("[B"));
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 Error("Internal error.");
360
        }
361
        if (!isSubTypeOf(value1, expected1)) {
362
            throw new AnalyzerException(insn, "First argument", "a "
363
                    + expected1 + " array reference", value1);
364
        } else if (!BasicValue.INT_VALUE.equals(value2)) {
365
            throw new AnalyzerException(insn, "Second argument",
366
                    BasicValue.INT_VALUE, value2);
367
        } else if (!isSubTypeOf(value3, expected3)) {
368
            throw new AnalyzerException(insn, "Third argument", expected3,
369
                    value3);
370
        }
371
        return null;
372
    }
373
374
    @Override
375
    public BasicValue naryOperation(final AbstractInsnNode insn,
376
            final List<? extends BasicValue> values) throws AnalyzerException {
377
        int opcode = insn.getOpcode();
378
        if (opcode == MULTIANEWARRAY) {
379
            for (int i = 0; i < values.size(); ++i) {
380
                if (!BasicValue.INT_VALUE.equals(values.get(i))) {
381
                    throw new AnalyzerException(insn, null,
382
                            BasicValue.INT_VALUE, values.get(i));
383
                }
384
            }
385
        } else {
386
            int i = 0;
387
            int j = 0;
388
            if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
389
                Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
390
                if (!isSubTypeOf(values.get(i++), newValue(owner))) {
391
                    throw new AnalyzerException(insn, "Method owner",
392
                            newValue(owner), values.get(0));
393
                }
394
            }
395
            String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
396
                    : ((MethodInsnNode) insn).desc;
397
            Type[] args = Type.getArgumentTypes(desc);
398
            while (i < values.size()) {
399
                BasicValue expected = newValue(args[j++]);
400
                BasicValue encountered = values.get(i++);
401
                if (!isSubTypeOf(encountered, expected)) {
402
                    throw new AnalyzerException(insn, "Argument " + j,
403
                            expected, encountered);
404
                }
405
            }
406
        }
407
        return super.naryOperation(insn, values);
408
    }
409
410
    @Override
411
    public void returnOperation(final AbstractInsnNode insn,
412
            final BasicValue value, final BasicValue expected)
413
            throws AnalyzerException {
414
        if (!isSubTypeOf(value, expected)) {
415
            throw new AnalyzerException(insn, "Incompatible return type",
416
                    expected, value);
417
        }
418
    }
419
420
    protected boolean isArrayValue(final BasicValue value) {
421
        return value.isReference();
422
    }
423
424
    protected BasicValue getElementValue(final BasicValue objectArrayValue)
425
            throws AnalyzerException {
426
        return BasicValue.REFERENCE_VALUE;
427
    }
428
429
    protected boolean isSubTypeOf(final BasicValue value,
430
            final BasicValue expected) {
431
        return value.equals(expected);
432
    }
433
}