/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * This file is available under and governed by the GNU General Public * License version 2 only, as published by the Free Software Foundation. * However, the following notice accompanied the original version of this * file: * * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package jdk.internal.org.objectweb.asm.util; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import jdk.internal.org.objectweb.asm.AnnotationVisitor; import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.ConstantDynamic; import jdk.internal.org.objectweb.asm.Handle; import jdk.internal.org.objectweb.asm.Label; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; import jdk.internal.org.objectweb.asm.TypePath; import jdk.internal.org.objectweb.asm.TypeReference; import jdk.internal.org.objectweb.asm.tree.MethodNode; import jdk.internal.org.objectweb.asm.tree.analysis.Analyzer; import jdk.internal.org.objectweb.asm.tree.analysis.AnalyzerException; import jdk.internal.org.objectweb.asm.tree.analysis.BasicValue; import jdk.internal.org.objectweb.asm.tree.analysis.BasicVerifier; /** * A {@link MethodVisitor} that checks that its methods are properly used. More precisely this * method adapter checks each instruction individually, i.e., each visit method checks some * preconditions based only on its arguments - such as the fact that the given opcode is * correct for a given visit method. This adapter can also perform some basic data flow checks (more * precisely those that can be performed without the full class hierarchy - see {@link * jdk.internal.org.objectweb.asm.tree.analysis.BasicVerifier}). For instance in a method whose signature is * {@code void m ()}, the invalid instruction IRETURN, or the invalid sequence IADD L2I will be * detected if the data flow checks are enabled. These checks are enabled by using the {@link * #CheckMethodAdapter(int,String,String,MethodVisitor,Map)} constructor. They are not performed if * any other constructor is used. * * @author Eric Bruneton */ public class CheckMethodAdapter extends MethodVisitor { /** The 'generic' instruction visit methods (i.e. those that take an opcode argument). */ private enum Method { VISIT_INSN, VISIT_INT_INSN, VISIT_VAR_INSN, VISIT_TYPE_INSN, VISIT_FIELD_INSN, VISIT_METHOD_INSN, VISIT_JUMP_INSN } /** The method to use to visit each instruction. Only generic methods are represented here. */ private static final Method[] OPCODE_METHODS = { Method.VISIT_INSN, // NOP Method.VISIT_INSN, // ACONST_NULL Method.VISIT_INSN, // ICONST_M1 Method.VISIT_INSN, // ICONST_0 Method.VISIT_INSN, // ICONST_1 Method.VISIT_INSN, // ICONST_2 Method.VISIT_INSN, // ICONST_3 Method.VISIT_INSN, // ICONST_4 Method.VISIT_INSN, // ICONST_5 Method.VISIT_INSN, // LCONST_0 Method.VISIT_INSN, // LCONST_1 Method.VISIT_INSN, // FCONST_0 Method.VISIT_INSN, // FCONST_1 Method.VISIT_INSN, // FCONST_2 Method.VISIT_INSN, // DCONST_0 Method.VISIT_INSN, // DCONST_1 Method.VISIT_INT_INSN, // BIPUSH Method.VISIT_INT_INSN, // SIPUSH null, // LDC null, // LDC_W null, // LDC2_W Method.VISIT_VAR_INSN, // ILOAD Method.VISIT_VAR_INSN, // LLOAD Method.VISIT_VAR_INSN, // FLOAD Method.VISIT_VAR_INSN, // DLOAD Method.VISIT_VAR_INSN, // ALOAD null, // ILOAD_0 null, // ILOAD_1 null, // ILOAD_2 null, // ILOAD_3 null, // LLOAD_0 null, // LLOAD_1 null, // LLOAD_2 null, // LLOAD_3 null, // FLOAD_0 null, // FLOAD_1 null, // FLOAD_2 null, // FLOAD_3 null, // DLOAD_0 null, // DLOAD_1 null, // DLOAD_2 null, // DLOAD_3 null, // ALOAD_0 null, // ALOAD_1 null, // ALOAD_2 null, // ALOAD_3 Method.VISIT_INSN, // IALOAD Method.VISIT_INSN, // LALOAD Method.VISIT_INSN, // FALOAD Method.VISIT_INSN, // DALOAD Method.VISIT_INSN, // AALOAD Method.VISIT_INSN, // BALOAD Method.VISIT_INSN, // CALOAD Method.VISIT_INSN, // SALOAD Method.VISIT_VAR_INSN, // ISTORE Method.VISIT_VAR_INSN, // LSTORE Method.VISIT_VAR_INSN, // FSTORE Method.VISIT_VAR_INSN, // DSTORE Method.VISIT_VAR_INSN, // ASTORE null, // ISTORE_0 null, // ISTORE_1 null, // ISTORE_2 null, // ISTORE_3 null, // LSTORE_0 null, // LSTORE_1 null, // LSTORE_2 null, // LSTORE_3 null, // FSTORE_0 null, // FSTORE_1 null, // FSTORE_2 null, // FSTORE_3 null, // DSTORE_0 null, // DSTORE_1 null, // DSTORE_2 null, // DSTORE_3 null, // ASTORE_0 null, // ASTORE_1 null, // ASTORE_2 null, // ASTORE_3 Method.VISIT_INSN, // IASTORE Method.VISIT_INSN, // LASTORE Method.VISIT_INSN, // FASTORE Method.VISIT_INSN, // DASTORE Method.VISIT_INSN, // AASTORE Method.VISIT_INSN, // BASTORE Method.VISIT_INSN, // CASTORE Method.VISIT_INSN, // SASTORE Method.VISIT_INSN, // POP Method.VISIT_INSN, // POP2 Method.VISIT_INSN, // DUP Method.VISIT_INSN, // DUP_X1 Method.VISIT_INSN, // DUP_X2 Method.VISIT_INSN, // DUP2 Method.VISIT_INSN, // DUP2_X1 Method.VISIT_INSN, // DUP2_X2 Method.VISIT_INSN, // SWAP Method.VISIT_INSN, // IADD Method.VISIT_INSN, // LADD Method.VISIT_INSN, // FADD Method.VISIT_INSN, // DADD Method.VISIT_INSN, // ISUB Method.VISIT_INSN, // LSUB Method.VISIT_INSN, // FSUB Method.VISIT_INSN, // DSUB Method.VISIT_INSN, // IMUL Method.VISIT_INSN, // LMUL Method.VISIT_INSN, // FMUL Method.VISIT_INSN, // DMUL Method.VISIT_INSN, // IDIV Method.VISIT_INSN, // LDIV Method.VISIT_INSN, // FDIV Method.VISIT_INSN, // DDIV Method.VISIT_INSN, // IREM Method.VISIT_INSN, // LREM Method.VISIT_INSN, // FREM Method.VISIT_INSN, // DREM Method.VISIT_INSN, // INEG Method.VISIT_INSN, // LNEG Method.VISIT_INSN, // FNEG Method.VISIT_INSN, // DNEG Method.VISIT_INSN, // ISHL Method.VISIT_INSN, // LSHL Method.VISIT_INSN, // ISHR Method.VISIT_INSN, // LSHR Method.VISIT_INSN, // IUSHR Method.VISIT_INSN, // LUSHR Method.VISIT_INSN, // IAND Method.VISIT_INSN, // LAND Method.VISIT_INSN, // IOR Method.VISIT_INSN, // LOR Method.VISIT_INSN, // IXOR Method.VISIT_INSN, // LXOR null, // IINC Method.VISIT_INSN, // I2L Method.VISIT_INSN, // I2F Method.VISIT_INSN, // I2D Method.VISIT_INSN, // L2I Method.VISIT_INSN, // L2F Method.VISIT_INSN, // L2D Method.VISIT_INSN, // F2I Method.VISIT_INSN, // F2L Method.VISIT_INSN, // F2D Method.VISIT_INSN, // D2I Method.VISIT_INSN, // D2L Method.VISIT_INSN, // D2F Method.VISIT_INSN, // I2B Method.VISIT_INSN, // I2C Method.VISIT_INSN, // I2S Method.VISIT_INSN, // LCMP Method.VISIT_INSN, // FCMPL Method.VISIT_INSN, // FCMPG Method.VISIT_INSN, // DCMPL Method.VISIT_INSN, // DCMPG Method.VISIT_JUMP_INSN, // IFEQ Method.VISIT_JUMP_INSN, // IFNE Method.VISIT_JUMP_INSN, // IFLT Method.VISIT_JUMP_INSN, // IFGE Method.VISIT_JUMP_INSN, // IFGT Method.VISIT_JUMP_INSN, // IFLE Method.VISIT_JUMP_INSN, // IF_ICMPEQ Method.VISIT_JUMP_INSN, // IF_ICMPNE Method.VISIT_JUMP_INSN, // IF_ICMPLT Method.VISIT_JUMP_INSN, // IF_ICMPGE Method.VISIT_JUMP_INSN, // IF_ICMPGT Method.VISIT_JUMP_INSN, // IF_ICMPLE Method.VISIT_JUMP_INSN, // IF_ACMPEQ Method.VISIT_JUMP_INSN, // IF_ACMPNE Method.VISIT_JUMP_INSN, // GOTO Method.VISIT_JUMP_INSN, // JSR Method.VISIT_VAR_INSN, // RET null, // TABLESWITCH null, // LOOKUPSWITCH Method.VISIT_INSN, // IRETURN Method.VISIT_INSN, // LRETURN Method.VISIT_INSN, // FRETURN Method.VISIT_INSN, // DRETURN Method.VISIT_INSN, // ARETURN Method.VISIT_INSN, // RETURN Method.VISIT_FIELD_INSN, // GETSTATIC Method.VISIT_FIELD_INSN, // PUTSTATIC Method.VISIT_FIELD_INSN, // GETFIELD Method.VISIT_FIELD_INSN, // PUTFIELD Method.VISIT_METHOD_INSN, // INVOKEVIRTUAL Method.VISIT_METHOD_INSN, // INVOKESPECIAL Method.VISIT_METHOD_INSN, // INVOKESTATIC Method.VISIT_METHOD_INSN, // INVOKEINTERFACE null, // INVOKEDYNAMIC Method.VISIT_TYPE_INSN, // NEW Method.VISIT_INT_INSN, // NEWARRAY Method.VISIT_TYPE_INSN, // ANEWARRAY Method.VISIT_INSN, // ARRAYLENGTH Method.VISIT_INSN, // ATHROW Method.VISIT_TYPE_INSN, // CHECKCAST Method.VISIT_TYPE_INSN, // INSTANCEOF Method.VISIT_INSN, // MONITORENTER Method.VISIT_INSN, // MONITOREXIT null, // WIDE null, // MULTIANEWARRAY Method.VISIT_JUMP_INSN, // IFNULL Method.VISIT_JUMP_INSN // IFNONNULL }; private static final String INVALID = "Invalid "; private static final String INVALID_DESCRIPTOR = "Invalid descriptor: "; private static final String INVALID_TYPE_REFERENCE = "Invalid type reference sort 0x"; private static final String INVALID_LOCAL_VARIABLE_INDEX = "Invalid local variable index"; private static final String MUST_NOT_BE_NULL_OR_EMPTY = " (must not be null or empty)"; private static final String START_LABEL = "start label"; private static final String END_LABEL = "end label"; /** The class version number. */ public int version; /** The access flags of the visited method. */ private int access; /** * The number of method parameters that can have runtime visible annotations. 0 means that all the * parameters from the method descriptor can have annotations. */ private int visibleAnnotableParameterCount; /** * The number of method parameters that can have runtime invisible annotations. 0 means that all * the parameters from the method descriptor can have annotations. */ private int invisibleAnnotableParameterCount; /** Whether the {@link #visitCode} method has been called. */ private boolean visitCodeCalled; /** Whether the {@link #visitMaxs} method has been called. */ private boolean visitMaxCalled; /** Whether the {@link #visitEnd} method has been called. */ private boolean visitEndCalled; /** The number of visited instructions so far. */ private int insnCount; /** The index of the instruction designated by each visited label. */ private final Map labelInsnIndices; /** The labels referenced by the visited method. */ private Set