1 // ASM: a very small and fast Java bytecode manipulation framework 2 // Copyright (c) 2000-2011 INRIA, France Telecom 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. Neither the name of the copyright holders nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 // THE POSSIBILITY OF SUCH DAMAGE. 28 package org.objectweb.asm; 29 30 import java.io.DataInputStream; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.util.regex.Pattern; 34 35 /** 36 * Defines additional JVM opcodes, access flags and constants which are not part of the ASM public 37 * API. 38 * 39 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a> 40 * @author Eric Bruneton 41 */ 42 final class Constants { 43 44 // The ClassFile attribute names, in the order they are defined in 45 // https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7-300. 46 47 static final String CONSTANT_VALUE = "ConstantValue"; 48 static final String CODE = "Code"; 49 static final String STACK_MAP_TABLE = "StackMapTable"; 50 static final String EXCEPTIONS = "Exceptions"; 51 static final String INNER_CLASSES = "InnerClasses"; 52 static final String ENCLOSING_METHOD = "EnclosingMethod"; 53 static final String SYNTHETIC = "Synthetic"; 54 static final String SIGNATURE = "Signature"; 55 static final String SOURCE_FILE = "SourceFile"; 56 static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension"; 57 static final String LINE_NUMBER_TABLE = "LineNumberTable"; 58 static final String LOCAL_VARIABLE_TABLE = "LocalVariableTable"; 59 static final String LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable"; 60 static final String DEPRECATED = "Deprecated"; 61 static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations"; 62 static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations"; 63 static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations"; 64 static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = 65 "RuntimeInvisibleParameterAnnotations"; 66 static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations"; 67 static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations"; 68 static final String ANNOTATION_DEFAULT = "AnnotationDefault"; 69 static final String BOOTSTRAP_METHODS = "BootstrapMethods"; 70 static final String METHOD_PARAMETERS = "MethodParameters"; 71 static final String MODULE = "Module"; 72 static final String MODULE_PACKAGES = "ModulePackages"; 73 static final String MODULE_MAIN_CLASS = "ModuleMainClass"; 74 static final String NEST_HOST = "NestHost"; 75 static final String NEST_MEMBERS = "NestMembers"; 76 static final String PERMITTED_SUBCLASSES = "PermittedSubclasses"; 77 static final String RECORD = "Record"; 78 79 // ASM specific access flags. 80 // WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard 81 // access flags, and also to make sure that these flags are automatically filtered out when 82 // written in class files (because access flags are stored using 16 bits only). 83 84 static final int ACC_CONSTRUCTOR = 0x40000; // method access flag. 85 86 // ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}. 87 88 /** 89 * A frame inserted between already existing frames. This internal stack map frame type (in 90 * addition to the ones declared in {@link Opcodes}) can only be used if the frame content can be 91 * computed from the previous existing frame and from the instructions between this existing frame 92 * and the inserted one, without any knowledge of the type hierarchy. This kind of frame is only 93 * used when an unconditional jump is inserted in a method while expanding an ASM specific 94 * instruction. Keep in sync with Opcodes.java. 95 */ 96 static final int F_INSERT = 256; 97 98 // The JVM opcode values which are not part of the ASM public API. 99 // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html. 100 101 static final int LDC_W = 19; 102 static final int LDC2_W = 20; 103 static final int ILOAD_0 = 26; 104 static final int ILOAD_1 = 27; 105 static final int ILOAD_2 = 28; 106 static final int ILOAD_3 = 29; 107 static final int LLOAD_0 = 30; 108 static final int LLOAD_1 = 31; 109 static final int LLOAD_2 = 32; 110 static final int LLOAD_3 = 33; 111 static final int FLOAD_0 = 34; 112 static final int FLOAD_1 = 35; 113 static final int FLOAD_2 = 36; 114 static final int FLOAD_3 = 37; 115 static final int DLOAD_0 = 38; 116 static final int DLOAD_1 = 39; 117 static final int DLOAD_2 = 40; 118 static final int DLOAD_3 = 41; 119 static final int ALOAD_0 = 42; 120 static final int ALOAD_1 = 43; 121 static final int ALOAD_2 = 44; 122 static final int ALOAD_3 = 45; 123 static final int ISTORE_0 = 59; 124 static final int ISTORE_1 = 60; 125 static final int ISTORE_2 = 61; 126 static final int ISTORE_3 = 62; 127 static final int LSTORE_0 = 63; 128 static final int LSTORE_1 = 64; 129 static final int LSTORE_2 = 65; 130 static final int LSTORE_3 = 66; 131 static final int FSTORE_0 = 67; 132 static final int FSTORE_1 = 68; 133 static final int FSTORE_2 = 69; 134 static final int FSTORE_3 = 70; 135 static final int DSTORE_0 = 71; 136 static final int DSTORE_1 = 72; 137 static final int DSTORE_2 = 73; 138 static final int DSTORE_3 = 74; 139 static final int ASTORE_0 = 75; 140 static final int ASTORE_1 = 76; 141 static final int ASTORE_2 = 77; 142 static final int ASTORE_3 = 78; 143 static final int WIDE = 196; 144 static final int GOTO_W = 200; 145 static final int JSR_W = 201; 146 147 // Constants to convert between normal and wide jump instructions. 148 149 // The delta between the GOTO_W and JSR_W opcodes and GOTO and JUMP. 150 static final int WIDE_JUMP_OPCODE_DELTA = GOTO_W - Opcodes.GOTO; 151 152 // Constants to convert JVM opcodes to the equivalent ASM specific opcodes, and vice versa. 153 154 // The delta between the ASM_IFEQ, ..., ASM_IF_ACMPNE, ASM_GOTO and ASM_JSR opcodes 155 // and IFEQ, ..., IF_ACMPNE, GOTO and JSR. 156 static final int ASM_OPCODE_DELTA = 49; 157 158 // The delta between the ASM_IFNULL and ASM_IFNONNULL opcodes and IFNULL and IFNONNULL. 159 static final int ASM_IFNULL_OPCODE_DELTA = 20; 160 161 // ASM specific opcodes, used for long forward jump instructions. 162 163 static final int ASM_IFEQ = Opcodes.IFEQ + ASM_OPCODE_DELTA; 164 static final int ASM_IFNE = Opcodes.IFNE + ASM_OPCODE_DELTA; 165 static final int ASM_IFLT = Opcodes.IFLT + ASM_OPCODE_DELTA; 166 static final int ASM_IFGE = Opcodes.IFGE + ASM_OPCODE_DELTA; 167 static final int ASM_IFGT = Opcodes.IFGT + ASM_OPCODE_DELTA; 168 static final int ASM_IFLE = Opcodes.IFLE + ASM_OPCODE_DELTA; 169 static final int ASM_IF_ICMPEQ = Opcodes.IF_ICMPEQ + ASM_OPCODE_DELTA; 170 static final int ASM_IF_ICMPNE = Opcodes.IF_ICMPNE + ASM_OPCODE_DELTA; 171 static final int ASM_IF_ICMPLT = Opcodes.IF_ICMPLT + ASM_OPCODE_DELTA; 172 static final int ASM_IF_ICMPGE = Opcodes.IF_ICMPGE + ASM_OPCODE_DELTA; 173 static final int ASM_IF_ICMPGT = Opcodes.IF_ICMPGT + ASM_OPCODE_DELTA; 174 static final int ASM_IF_ICMPLE = Opcodes.IF_ICMPLE + ASM_OPCODE_DELTA; 175 static final int ASM_IF_ACMPEQ = Opcodes.IF_ACMPEQ + ASM_OPCODE_DELTA; 176 static final int ASM_IF_ACMPNE = Opcodes.IF_ACMPNE + ASM_OPCODE_DELTA; 177 static final int ASM_GOTO = Opcodes.GOTO + ASM_OPCODE_DELTA; 178 static final int ASM_JSR = Opcodes.JSR + ASM_OPCODE_DELTA; 179 static final int ASM_IFNULL = Opcodes.IFNULL + ASM_IFNULL_OPCODE_DELTA; 180 static final int ASM_IFNONNULL = Opcodes.IFNONNULL + ASM_IFNULL_OPCODE_DELTA; 181 static final int ASM_GOTO_W = 220; 182 Constants()183 private Constants() {} 184 checkAsmExperimental(final Object caller)185 static void checkAsmExperimental(final Object caller) { 186 Class<?> callerClass = caller.getClass(); 187 String internalName = callerClass.getName().replace('.', '/'); 188 if (!isWhitelisted(internalName)) { 189 checkIsPreview(callerClass.getClassLoader().getResourceAsStream(internalName + ".class")); 190 } 191 } 192 isWhitelisted(final String internalName)193 static boolean isWhitelisted(final String internalName) { 194 if (!internalName.startsWith("org/objectweb/asm/")) { 195 return false; 196 } 197 String member = "(Annotation|Class|Field|Method|Module|RecordComponent|Signature)"; 198 return internalName.contains("Test$") 199 || Pattern.matches( 200 "org/objectweb/asm/util/Trace" + member + "Visitor(\\$.*)?", internalName) 201 || Pattern.matches( 202 "org/objectweb/asm/util/Check" + member + "Adapter(\\$.*)?", internalName); 203 } 204 checkIsPreview(final InputStream classInputStream)205 static void checkIsPreview(final InputStream classInputStream) { 206 if (classInputStream == null) { 207 throw new IllegalStateException("Bytecode not available, can't check class version"); 208 } 209 int minorVersion; 210 try (DataInputStream callerClassStream = new DataInputStream(classInputStream); ) { 211 callerClassStream.readInt(); 212 minorVersion = callerClassStream.readUnsignedShort(); 213 } catch (IOException ioe) { 214 throw new IllegalStateException("I/O error, can't check class version", ioe); 215 } 216 if (minorVersion != 0xFFFF) { 217 throw new IllegalStateException( 218 "ASM9_EXPERIMENTAL can only be used by classes compiled with --enable-preview"); 219 } 220 } 221 } 222