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