All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.tools.asm.util.CheckMethodAdapter Maven / Gradle / Ivy

There is a newer version: 9.7.1-scala-1
Show newest version
// 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 scala.tools.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 scala.tools.asm.AnnotationVisitor;
import scala.tools.asm.Attribute;
import scala.tools.asm.ConstantDynamic;
import scala.tools.asm.Handle;
import scala.tools.asm.Label;
import scala.tools.asm.MethodVisitor;
import scala.tools.asm.Opcodes;
import scala.tools.asm.Type;
import scala.tools.asm.TypePath;
import scala.tools.asm.TypeReference;
import scala.tools.asm.tree.MethodNode;
import scala.tools.asm.tree.analysis.Analyzer;
import scala.tools.asm.tree.analysis.AnalyzerException;
import scala.tools.asm.tree.analysis.BasicValue;
import scala.tools.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
 * scala.tools.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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy