1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 only, as
6  * published by the Free Software Foundation.  Oracle designates this
7  * particular file as subject to the "Classpath" exception as provided
8  * by Oracle in the LICENSE file that accompanied this code.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /*
26  * This file is available under and governed by the GNU General Public
27  * License version 2 only, as published by the Free Software Foundation.
28  * However, the following notice accompanied the original version of this
29  * file:
30  *
31  * ASM: a very small and fast Java bytecode manipulation framework
32  * Copyright (c) 2000-2011 INRIA, France Telecom
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  * 3. Neither the name of the copyright holders nor the names of its
44  *    contributors may be used to endorse or promote products derived from
45  *    this software without specific prior written permission.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57  * THE POSSIBILITY OF SUCH DAMAGE.
58  */
59 package jdk.internal.org.objectweb.asm.tree.analysis;
60 
61 import java.util.List;
62 
63 import jdk.internal.org.objectweb.asm.Type;
64 import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
65 import jdk.internal.org.objectweb.asm.tree.FieldInsnNode;
66 import jdk.internal.org.objectweb.asm.tree.InvokeDynamicInsnNode;
67 import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
68 
69 /**
70  * An extended {@link BasicInterpreter} that checks that bytecode instructions
71  * are correctly used.
72  *
73  * @author Eric Bruneton
74  * @author Bing Ran
75  */
76 public class BasicVerifier extends BasicInterpreter {
77 
BasicVerifier()78     public BasicVerifier() {
79         super(ASM5);
80     }
81 
BasicVerifier(final int api)82     protected BasicVerifier(final int api) {
83         super(api);
84     }
85 
86     @Override
copyOperation(final AbstractInsnNode insn, final BasicValue value)87     public BasicValue copyOperation(final AbstractInsnNode insn,
88             final BasicValue value) throws AnalyzerException {
89         Value expected;
90         switch (insn.getOpcode()) {
91         case ILOAD:
92         case ISTORE:
93             expected = BasicValue.INT_VALUE;
94             break;
95         case FLOAD:
96         case FSTORE:
97             expected = BasicValue.FLOAT_VALUE;
98             break;
99         case LLOAD:
100         case LSTORE:
101             expected = BasicValue.LONG_VALUE;
102             break;
103         case DLOAD:
104         case DSTORE:
105             expected = BasicValue.DOUBLE_VALUE;
106             break;
107         case ALOAD:
108             if (!value.isReference()) {
109                 throw new AnalyzerException(insn, null, "an object reference",
110                         value);
111             }
112             return value;
113         case ASTORE:
114             if (!value.isReference()
115                     && !BasicValue.RETURNADDRESS_VALUE.equals(value)) {
116                 throw new AnalyzerException(insn, null,
117                         "an object reference or a return address", value);
118             }
119             return value;
120         default:
121             return value;
122         }
123         if (!expected.equals(value)) {
124             throw new AnalyzerException(insn, null, expected, value);
125         }
126         return value;
127     }
128 
129     @Override
unaryOperation(final AbstractInsnNode insn, final BasicValue value)130     public BasicValue unaryOperation(final AbstractInsnNode insn,
131             final BasicValue value) throws AnalyzerException {
132         BasicValue expected;
133         switch (insn.getOpcode()) {
134         case INEG:
135         case IINC:
136         case I2F:
137         case I2L:
138         case I2D:
139         case I2B:
140         case I2C:
141         case I2S:
142         case IFEQ:
143         case IFNE:
144         case IFLT:
145         case IFGE:
146         case IFGT:
147         case IFLE:
148         case TABLESWITCH:
149         case LOOKUPSWITCH:
150         case IRETURN:
151         case NEWARRAY:
152         case ANEWARRAY:
153             expected = BasicValue.INT_VALUE;
154             break;
155         case FNEG:
156         case F2I:
157         case F2L:
158         case F2D:
159         case FRETURN:
160             expected = BasicValue.FLOAT_VALUE;
161             break;
162         case LNEG:
163         case L2I:
164         case L2F:
165         case L2D:
166         case LRETURN:
167             expected = BasicValue.LONG_VALUE;
168             break;
169         case DNEG:
170         case D2I:
171         case D2F:
172         case D2L:
173         case DRETURN:
174             expected = BasicValue.DOUBLE_VALUE;
175             break;
176         case GETFIELD:
177             expected = newValue(Type
178                     .getObjectType(((FieldInsnNode) insn).owner));
179             break;
180         case CHECKCAST:
181             if (!value.isReference()) {
182                 throw new AnalyzerException(insn, null, "an object reference",
183                         value);
184             }
185             return super.unaryOperation(insn, value);
186         case ARRAYLENGTH:
187             if (!isArrayValue(value)) {
188                 throw new AnalyzerException(insn, null, "an array reference",
189                         value);
190             }
191             return super.unaryOperation(insn, value);
192         case ARETURN:
193         case ATHROW:
194         case INSTANCEOF:
195         case MONITORENTER:
196         case MONITOREXIT:
197         case IFNULL:
198         case IFNONNULL:
199             if (!value.isReference()) {
200                 throw new AnalyzerException(insn, null, "an object reference",
201                         value);
202             }
203             return super.unaryOperation(insn, value);
204         case PUTSTATIC:
205             expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
206             break;
207         default:
208             throw new Error("Internal error.");
209         }
210         if (!isSubTypeOf(value, expected)) {
211             throw new AnalyzerException(insn, null, expected, value);
212         }
213         return super.unaryOperation(insn, value);
214     }
215 
216     @Override
binaryOperation(final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2)217     public BasicValue binaryOperation(final AbstractInsnNode insn,
218             final BasicValue value1, final BasicValue value2)
219             throws AnalyzerException {
220         BasicValue expected1;
221         BasicValue expected2;
222         switch (insn.getOpcode()) {
223         case IALOAD:
224             expected1 = newValue(Type.getType("[I"));
225             expected2 = BasicValue.INT_VALUE;
226             break;
227         case BALOAD:
228             if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
229                 expected1 = newValue(Type.getType("[Z"));
230             } else {
231                 expected1 = newValue(Type.getType("[B"));
232             }
233             expected2 = BasicValue.INT_VALUE;
234             break;
235         case CALOAD:
236             expected1 = newValue(Type.getType("[C"));
237             expected2 = BasicValue.INT_VALUE;
238             break;
239         case SALOAD:
240             expected1 = newValue(Type.getType("[S"));
241             expected2 = BasicValue.INT_VALUE;
242             break;
243         case LALOAD:
244             expected1 = newValue(Type.getType("[J"));
245             expected2 = BasicValue.INT_VALUE;
246             break;
247         case FALOAD:
248             expected1 = newValue(Type.getType("[F"));
249             expected2 = BasicValue.INT_VALUE;
250             break;
251         case DALOAD:
252             expected1 = newValue(Type.getType("[D"));
253             expected2 = BasicValue.INT_VALUE;
254             break;
255         case AALOAD:
256             expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
257             expected2 = BasicValue.INT_VALUE;
258             break;
259         case IADD:
260         case ISUB:
261         case IMUL:
262         case IDIV:
263         case IREM:
264         case ISHL:
265         case ISHR:
266         case IUSHR:
267         case IAND:
268         case IOR:
269         case IXOR:
270         case IF_ICMPEQ:
271         case IF_ICMPNE:
272         case IF_ICMPLT:
273         case IF_ICMPGE:
274         case IF_ICMPGT:
275         case IF_ICMPLE:
276             expected1 = BasicValue.INT_VALUE;
277             expected2 = BasicValue.INT_VALUE;
278             break;
279         case FADD:
280         case FSUB:
281         case FMUL:
282         case FDIV:
283         case FREM:
284         case FCMPL:
285         case FCMPG:
286             expected1 = BasicValue.FLOAT_VALUE;
287             expected2 = BasicValue.FLOAT_VALUE;
288             break;
289         case LADD:
290         case LSUB:
291         case LMUL:
292         case LDIV:
293         case LREM:
294         case LAND:
295         case LOR:
296         case LXOR:
297         case LCMP:
298             expected1 = BasicValue.LONG_VALUE;
299             expected2 = BasicValue.LONG_VALUE;
300             break;
301         case LSHL:
302         case LSHR:
303         case LUSHR:
304             expected1 = BasicValue.LONG_VALUE;
305             expected2 = BasicValue.INT_VALUE;
306             break;
307         case DADD:
308         case DSUB:
309         case DMUL:
310         case DDIV:
311         case DREM:
312         case DCMPL:
313         case DCMPG:
314             expected1 = BasicValue.DOUBLE_VALUE;
315             expected2 = BasicValue.DOUBLE_VALUE;
316             break;
317         case IF_ACMPEQ:
318         case IF_ACMPNE:
319             expected1 = BasicValue.REFERENCE_VALUE;
320             expected2 = BasicValue.REFERENCE_VALUE;
321             break;
322         case PUTFIELD:
323             FieldInsnNode fin = (FieldInsnNode) insn;
324             expected1 = newValue(Type.getObjectType(fin.owner));
325             expected2 = newValue(Type.getType(fin.desc));
326             break;
327         default:
328             throw new Error("Internal error.");
329         }
330         if (!isSubTypeOf(value1, expected1)) {
331             throw new AnalyzerException(insn, "First argument", expected1,
332                     value1);
333         } else if (!isSubTypeOf(value2, expected2)) {
334             throw new AnalyzerException(insn, "Second argument", expected2,
335                     value2);
336         }
337         if (insn.getOpcode() == AALOAD) {
338             return getElementValue(value1);
339         } else {
340             return super.binaryOperation(insn, value1, value2);
341         }
342     }
343 
344     @Override
ternaryOperation(final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2, final BasicValue value3)345     public BasicValue ternaryOperation(final AbstractInsnNode insn,
346             final BasicValue value1, final BasicValue value2,
347             final BasicValue value3) throws AnalyzerException {
348         BasicValue expected1;
349         BasicValue expected3;
350         switch (insn.getOpcode()) {
351         case IASTORE:
352             expected1 = newValue(Type.getType("[I"));
353             expected3 = BasicValue.INT_VALUE;
354             break;
355         case BASTORE:
356             if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
357                 expected1 = newValue(Type.getType("[Z"));
358             } else {
359                 expected1 = newValue(Type.getType("[B"));
360             }
361             expected3 = BasicValue.INT_VALUE;
362             break;
363         case CASTORE:
364             expected1 = newValue(Type.getType("[C"));
365             expected3 = BasicValue.INT_VALUE;
366             break;
367         case SASTORE:
368             expected1 = newValue(Type.getType("[S"));
369             expected3 = BasicValue.INT_VALUE;
370             break;
371         case LASTORE:
372             expected1 = newValue(Type.getType("[J"));
373             expected3 = BasicValue.LONG_VALUE;
374             break;
375         case FASTORE:
376             expected1 = newValue(Type.getType("[F"));
377             expected3 = BasicValue.FLOAT_VALUE;
378             break;
379         case DASTORE:
380             expected1 = newValue(Type.getType("[D"));
381             expected3 = BasicValue.DOUBLE_VALUE;
382             break;
383         case AASTORE:
384             expected1 = value1;
385             expected3 = BasicValue.REFERENCE_VALUE;
386             break;
387         default:
388             throw new Error("Internal error.");
389         }
390         if (!isSubTypeOf(value1, expected1)) {
391             throw new AnalyzerException(insn, "First argument", "a "
392                     + expected1 + " array reference", value1);
393         } else if (!BasicValue.INT_VALUE.equals(value2)) {
394             throw new AnalyzerException(insn, "Second argument",
395                     BasicValue.INT_VALUE, value2);
396         } else if (!isSubTypeOf(value3, expected3)) {
397             throw new AnalyzerException(insn, "Third argument", expected3,
398                     value3);
399         }
400         return null;
401     }
402 
403     @Override
naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values)404     public BasicValue naryOperation(final AbstractInsnNode insn,
405             final List<? extends BasicValue> values) throws AnalyzerException {
406         int opcode = insn.getOpcode();
407         if (opcode == MULTIANEWARRAY) {
408             for (int i = 0; i < values.size(); ++i) {
409                 if (!BasicValue.INT_VALUE.equals(values.get(i))) {
410                     throw new AnalyzerException(insn, null,
411                             BasicValue.INT_VALUE, values.get(i));
412                 }
413             }
414         } else {
415             int i = 0;
416             int j = 0;
417             if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
418                 Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
419                 if (!isSubTypeOf(values.get(i++), newValue(owner))) {
420                     throw new AnalyzerException(insn, "Method owner",
421                             newValue(owner), values.get(0));
422                 }
423             }
424             String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
425                     : ((MethodInsnNode) insn).desc;
426             Type[] args = Type.getArgumentTypes(desc);
427             while (i < values.size()) {
428                 BasicValue expected = newValue(args[j++]);
429                 BasicValue encountered = values.get(i++);
430                 if (!isSubTypeOf(encountered, expected)) {
431                     throw new AnalyzerException(insn, "Argument " + j,
432                             expected, encountered);
433                 }
434             }
435         }
436         return super.naryOperation(insn, values);
437     }
438 
439     @Override
returnOperation(final AbstractInsnNode insn, final BasicValue value, final BasicValue expected)440     public void returnOperation(final AbstractInsnNode insn,
441             final BasicValue value, final BasicValue expected)
442             throws AnalyzerException {
443         if (!isSubTypeOf(value, expected)) {
444             throw new AnalyzerException(insn, "Incompatible return type",
445                     expected, value);
446         }
447     }
448 
isArrayValue(final BasicValue value)449     protected boolean isArrayValue(final BasicValue value) {
450         return value.isReference();
451     }
452 
getElementValue(final BasicValue objectArrayValue)453     protected BasicValue getElementValue(final BasicValue objectArrayValue)
454             throws AnalyzerException {
455         return BasicValue.REFERENCE_VALUE;
456     }
457 
isSubTypeOf(final BasicValue value, final BasicValue expected)458     protected boolean isSubTypeOf(final BasicValue value,
459             final BasicValue expected) {
460         return value.equals(expected);
461     }
462 }
463