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 }