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