001/*** 002 * ASM: a very small and fast Java bytecode manipulation framework 003 * Copyright (c) 2000-2011 INRIA, France Telecom 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions 008 * are met: 009 * 1. Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 2. Redistributions in binary form must reproduce the above copyright 012 * notice, this list of conditions and the following disclaimer in the 013 * documentation and/or other materials provided with the distribution. 014 * 3. Neither the name of the copyright holders nor the names of its 015 * contributors may be used to endorse or promote products derived from 016 * this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 028 * THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package io.ebean.enhance.asm.tree.analysis; 031 032import io.ebean.enhance.asm.Type; 033import io.ebean.enhance.asm.tree.AbstractInsnNode; 034import io.ebean.enhance.asm.tree.FieldInsnNode; 035import io.ebean.enhance.asm.tree.InvokeDynamicInsnNode; 036import io.ebean.enhance.asm.tree.MethodInsnNode; 037 038import java.util.List; 039 040/** 041 * An extended {@link BasicInterpreter} that checks that bytecode instructions 042 * are correctly used. 043 * 044 * @author Eric Bruneton 045 * @author Bing Ran 046 */ 047public class BasicVerifier extends BasicInterpreter { 048 049 public BasicVerifier() { 050 super(ASM6); 051 } 052 053 protected BasicVerifier(final int api) { 054 super(api); 055 } 056 057 @Override 058 public BasicValue copyOperation(final AbstractInsnNode insn, 059 final BasicValue value) throws AnalyzerException { 060 Value expected; 061 switch (insn.getOpcode()) { 062 case ILOAD: 063 case ISTORE: 064 expected = BasicValue.INT_VALUE; 065 break; 066 case FLOAD: 067 case FSTORE: 068 expected = BasicValue.FLOAT_VALUE; 069 break; 070 case LLOAD: 071 case LSTORE: 072 expected = BasicValue.LONG_VALUE; 073 break; 074 case DLOAD: 075 case DSTORE: 076 expected = BasicValue.DOUBLE_VALUE; 077 break; 078 case ALOAD: 079 if (!value.isReference()) { 080 throw new AnalyzerException(insn, null, "an object reference", 081 value); 082 } 083 return value; 084 case ASTORE: 085 if (!value.isReference() 086 && !BasicValue.RETURNADDRESS_VALUE.equals(value)) { 087 throw new AnalyzerException(insn, null, 088 "an object reference or a return address", value); 089 } 090 return value; 091 default: 092 return value; 093 } 094 if (!expected.equals(value)) { 095 throw new AnalyzerException(insn, null, expected, value); 096 } 097 return value; 098 } 099 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}