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 BasicVerifier()78 public BasicVerifier() { 79 super(ASM5); 80 } 81 BasicVerifier(final int api)82 protected BasicVerifier(final int api) { 83 super(api); 84 } 85 86 @Override copyOperation(final AbstractInsnNode insn, final BasicValue value)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 unaryOperation(final AbstractInsnNode insn, final BasicValue value)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 binaryOperation(final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2)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 ternaryOperation(final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2, final BasicValue value3)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 naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values)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 returnOperation(final AbstractInsnNode insn, final BasicValue value, final BasicValue expected)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 isArrayValue(final BasicValue value)449 protected boolean isArrayValue(final BasicValue value) { 450 return value.isReference(); 451 } 452 getElementValue(final BasicValue objectArrayValue)453 protected BasicValue getElementValue(final BasicValue objectArrayValue) 454 throws AnalyzerException { 455 return BasicValue.REFERENCE_VALUE; 456 } 457 isSubTypeOf(final BasicValue value, final BasicValue expected)458 protected boolean isSubTypeOf(final BasicValue value, 459 final BasicValue expected) { 460 return value.equals(expected); 461 } 462 } 463