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.util;
  60 
  61 import java.io.FileInputStream;
  62 import java.io.PrintWriter;
  63 import java.util.ArrayList;
  64 import java.util.HashMap;
  65 import java.util.Iterator;
  66 import java.util.List;
  67 import java.util.Map;
  68 
  69 import jdk.internal.org.objectweb.asm.AnnotationVisitor;
  70 import jdk.internal.org.objectweb.asm.Attribute;
  71 import jdk.internal.org.objectweb.asm.ClassReader;
  72 import jdk.internal.org.objectweb.asm.ClassVisitor;
  73 import jdk.internal.org.objectweb.asm.FieldVisitor;
  74 import jdk.internal.org.objectweb.asm.Label;
  75 import jdk.internal.org.objectweb.asm.MethodVisitor;
  76 import jdk.internal.org.objectweb.asm.Opcodes;
  77 import jdk.internal.org.objectweb.asm.Type;
  78 import jdk.internal.org.objectweb.asm.TypePath;
  79 import jdk.internal.org.objectweb.asm.TypeReference;
  80 import jdk.internal.org.objectweb.asm.tree.ClassNode;
  81 import jdk.internal.org.objectweb.asm.tree.MethodNode;
  82 import jdk.internal.org.objectweb.asm.tree.analysis.Analyzer;
  83 import jdk.internal.org.objectweb.asm.tree.analysis.BasicValue;
  84 import jdk.internal.org.objectweb.asm.tree.analysis.Frame;
  85 import jdk.internal.org.objectweb.asm.tree.analysis.SimpleVerifier;
  86 
  87 /**
  88  * A {@link ClassVisitor} that checks that its methods are properly used. More
  89  * precisely this class adapter checks each method call individually, based
  90  * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i>
  91  * of method calls. For example, the invalid sequence
  92  * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
  93  * "i", "D", null)</tt> will <i>not</i> be detected by this class adapter.
  94  *
  95  * <p>
  96  * <code>CheckClassAdapter</code> can be also used to verify bytecode
  97  * transformations in order to make sure transformed bytecode is sane. For
  98  * example:
  99  *
 100  * <pre>
 101  *   InputStream is = ...; // get bytes for the source class
 102  *   ClassReader cr = new ClassReader(is);
 103  *   ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
 104  *   ClassVisitor cv = new <b>MyClassAdapter</b>(new CheckClassAdapter(cw));
 105  *   cr.accept(cv, 0);
 106  *
 107  *   StringWriter sw = new StringWriter();
 108  *   PrintWriter pw = new PrintWriter(sw);
 109  *   CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, pw);
 110  *   assertTrue(sw.toString(), sw.toString().length()==0);
 111  * </pre>
 112  *
 113  * Above code runs transformed bytecode trough the
 114  * <code>CheckClassAdapter</code>. It won't be exactly the same verification as
 115  * JVM does, but it run data flow analysis for the code of each method and
 116  * checks that expectations are met for each method instruction.
 117  *
 118  * <p>
 119  * If method bytecode has errors, assertion text will show the erroneous
 120  * instruction number and dump of the failed method with information about
 121  * locals and stack slot for each instruction. For example (format is -
 122  * insnNumber locals : stack):
 123  *
 124  * <pre>
 125  * jdk.internal.org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found .
 126  *   at jdk.internal.org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289)
 127  *   at jdk.internal.org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135)
 128  * ...
 129  * remove()V
 130  * 00000 LinkedBlockingQueue$Itr . . . . . . . .  :
 131  *   ICONST_0
 132  * 00001 LinkedBlockingQueue$Itr . . . . . . . .  : I
 133  *   ISTORE 2
 134  * 00001 LinkedBlockingQueue$Itr <b>.</b> I . . . . . .  :
 135  * ...
 136  *
 137  * 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . .  :
 138  *   ILOAD 1
 139  * 00072 <b>?</b>
 140  *   INVOKESPECIAL java/lang/Integer.&lt;init&gt; (I)V
 141  * ...
 142  * </pre>
 143  *
 144  * In the above output you can see that variable 1 loaded by
 145  * <code>ILOAD 1</code> instruction at position <code>00071</code> is not
 146  * initialized. You can also see that at the beginning of the method (code
 147  * inserted by the transformation) variable 2 is initialized.
 148  *
 149  * <p>
 150  * Note that when used like that, <code>CheckClassAdapter.verify()</code> can
 151  * trigger additional class loading, because it is using
 152  * <code>SimpleVerifier</code>.
 153  *
 154  * @author Eric Bruneton
 155  */
 156 public class CheckClassAdapter extends ClassVisitor {
 157 
 158     /**
 159      * The class version number.
 160      */
 161     private int version;
 162 
 163     /**
 164      * <tt>true</tt> if the visit method has been called.
 165      */
 166     private boolean start;
 167 
 168     /**
 169      * <tt>true</tt> if the visitSource method has been called.
 170      */
 171     private boolean source;
 172 
 173     /**
 174      * <tt>true</tt> if the visitOuterClass method has been called.
 175      */
 176     private boolean outer;
 177 
 178     /**
 179      * <tt>true</tt> if the visitEnd method has been called.
 180      */
 181     private boolean end;
 182 
 183     /**
 184      * The already visited labels. This map associate Integer values to Label
 185      * keys.
 186      */
 187     private Map<Label, Integer> labels;
 188 
 189     /**
 190      * <tt>true</tt> if the method code must be checked with a BasicVerifier.
 191      */
 192     private boolean checkDataFlow;
 193 
 194     /**
 195      * Checks a given class.
 196      * <p>
 197      * Usage: CheckClassAdapter &lt;binary class name or class file name&gt;
 198      *
 199      * @param args
 200      *            the command line arguments.
 201      *
 202      * @throws Exception
 203      *             if the class cannot be found, or if an IO exception occurs.
 204      */
 205     public static void main(final String[] args) throws Exception {
 206         if (args.length != 1) {
 207             System.err.println("Verifies the given class.");
 208             System.err.println("Usage: CheckClassAdapter "
 209                     + "<fully qualified class name or class file name>");
 210             return;
 211         }
 212         ClassReader cr;
 213         if (args[0].endsWith(".class")) {
 214             cr = new ClassReader(new FileInputStream(args[0]));
 215         } else {
 216             cr = new ClassReader(args[0]);
 217         }
 218 
 219         verify(cr, false, new PrintWriter(System.err));
 220     }
 221 
 222     /**
 223      * Checks a given class.
 224      *
 225      * @param cr
 226      *            a <code>ClassReader</code> that contains bytecode for the
 227      *            analysis.
 228      * @param loader
 229      *            a <code>ClassLoader</code> which will be used to load
 230      *            referenced classes. This is useful if you are verifiying
 231      *            multiple interdependent classes.
 232      * @param dump
 233      *            true if bytecode should be printed out not only when errors
 234      *            are found.
 235      * @param pw
 236      *            write where results going to be printed
 237      */
 238     public static void verify(final ClassReader cr, final ClassLoader loader,
 239             final boolean dump, final PrintWriter pw) {
 240         ClassNode cn = new ClassNode();
 241         cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG);
 242 
 243         Type syperType = cn.superName == null ? null : Type
 244                 .getObjectType(cn.superName);
 245         List<MethodNode> methods = cn.methods;
 246 
 247         List<Type> interfaces = new ArrayList<Type>();
 248         for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) {
 249             interfaces.add(Type.getObjectType(i.next().toString()));
 250         }
 251 
 252         for (int i = 0; i < methods.size(); ++i) {
 253             MethodNode method = methods.get(i);
 254             SimpleVerifier verifier = new SimpleVerifier(
 255                     Type.getObjectType(cn.name), syperType, interfaces,
 256                     (cn.access & Opcodes.ACC_INTERFACE) != 0);
 257             Analyzer<BasicValue> a = new Analyzer<BasicValue>(verifier);
 258             if (loader != null) {
 259                 verifier.setClassLoader(loader);
 260             }
 261             try {
 262                 a.analyze(cn.name, method);
 263                 if (!dump) {
 264                     continue;
 265                 }
 266             } catch (Exception e) {
 267                 e.printStackTrace(pw);
 268             }
 269             printAnalyzerResult(method, a, pw);
 270         }
 271         pw.flush();
 272     }
 273 
 274     /**
 275      * Checks a given class
 276      *
 277      * @param cr
 278      *            a <code>ClassReader</code> that contains bytecode for the
 279      *            analysis.
 280      * @param dump
 281      *            true if bytecode should be printed out not only when errors
 282      *            are found.
 283      * @param pw
 284      *            write where results going to be printed
 285      */
 286     public static void verify(final ClassReader cr, final boolean dump,
 287             final PrintWriter pw) {
 288         verify(cr, null, dump, pw);
 289     }
 290 
 291     static void printAnalyzerResult(MethodNode method, Analyzer<BasicValue> a,
 292             final PrintWriter pw) {
 293         Frame<BasicValue>[] frames = a.getFrames();
 294         Textifier t = new Textifier();
 295         TraceMethodVisitor mv = new TraceMethodVisitor(t);
 296 
 297         pw.println(method.name + method.desc);
 298         for (int j = 0; j < method.instructions.size(); ++j) {
 299             method.instructions.get(j).accept(mv);
 300 
 301             StringBuffer s = new StringBuffer();
 302             Frame<BasicValue> f = frames[j];
 303             if (f == null) {
 304                 s.append('?');
 305             } else {
 306                 for (int k = 0; k < f.getLocals(); ++k) {
 307                     s.append(getShortName(f.getLocal(k).toString()))
 308                             .append(' ');
 309                 }
 310                 s.append(" : ");
 311                 for (int k = 0; k < f.getStackSize(); ++k) {
 312                     s.append(getShortName(f.getStack(k).toString()))
 313                             .append(' ');
 314                 }
 315             }
 316             while (s.length() < method.maxStack + method.maxLocals + 1) {
 317                 s.append(' ');
 318             }
 319             pw.print(Integer.toString(j + 100000).substring(1));
 320             pw.print(" " + s + " : " + t.text.get(t.text.size() - 1));
 321         }
 322         for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
 323             method.tryCatchBlocks.get(j).accept(mv);
 324             pw.print(" " + t.text.get(t.text.size() - 1));
 325         }
 326         pw.println();
 327     }
 328 
 329     private static String getShortName(final String name) {
 330         int n = name.lastIndexOf('/');
 331         int k = name.length();
 332         if (name.charAt(k - 1) == ';') {
 333             k--;
 334         }
 335         return n == -1 ? name : name.substring(n + 1, k);
 336     }
 337 
 338     /**
 339      * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
 340      * this constructor</i>. Instead, they must use the
 341      * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
 342      *
 343      * @param cv
 344      *            the class visitor to which this adapter must delegate calls.
 345      */
 346     public CheckClassAdapter(final ClassVisitor cv) {
 347         this(cv, true);
 348     }
 349 
 350     /**
 351      * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
 352      * this constructor</i>. Instead, they must use the
 353      * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
 354      *
 355      * @param cv
 356      *            the class visitor to which this adapter must delegate calls.
 357      * @param checkDataFlow
 358      *            <tt>true</tt> to perform basic data flow checks, or
 359      *            <tt>false</tt> to not perform any data flow check (see
 360      *            {@link CheckMethodAdapter}). This option requires valid
 361      *            maxLocals and maxStack values.
 362      */
 363     public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) {
 364         this(Opcodes.ASM5, cv, checkDataFlow);
 365     }
 366 
 367     /**
 368      * Constructs a new {@link CheckClassAdapter}.
 369      *
 370      * @param api
 371      *            the ASM API version implemented by this visitor. Must be one
 372      *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
 373      * @param cv
 374      *            the class visitor to which this adapter must delegate calls.
 375      * @param checkDataFlow
 376      *            <tt>true</tt> to perform basic data flow checks, or
 377      *            <tt>false</tt> to not perform any data flow check (see
 378      *            {@link CheckMethodAdapter}). This option requires valid
 379      *            maxLocals and maxStack values.
 380      */
 381     protected CheckClassAdapter(final int api, final ClassVisitor cv,
 382             final boolean checkDataFlow) {
 383         super(api, cv);
 384         this.labels = new HashMap<Label, Integer>();
 385         this.checkDataFlow = checkDataFlow;
 386     }
 387 
 388     // ------------------------------------------------------------------------
 389     // Implementation of the ClassVisitor interface
 390     // ------------------------------------------------------------------------
 391 
 392     @Override
 393     public void visit(final int version, final int access, final String name,
 394             final String signature, final String superName,
 395             final String[] interfaces) {
 396         if (start) {
 397             throw new IllegalStateException("visit must be called only once");
 398         }
 399         start = true;
 400         checkState();
 401         checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
 402                 + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
 403                 + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
 404                 + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
 405                 + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
 406         if (name == null || !name.endsWith("package-info")) {
 407             CheckMethodAdapter.checkInternalName(name, "class name");
 408         }
 409         if ("java/lang/Object".equals(name)) {
 410             if (superName != null) {
 411                 throw new IllegalArgumentException(
 412                         "The super class name of the Object class must be 'null'");
 413             }
 414         } else {
 415             CheckMethodAdapter.checkInternalName(superName, "super class name");
 416         }
 417         if (signature != null) {
 418             checkClassSignature(signature);
 419         }
 420         if ((access & Opcodes.ACC_INTERFACE) != 0) {
 421             if (!"java/lang/Object".equals(superName)) {
 422                 throw new IllegalArgumentException(
 423                         "The super class name of interfaces must be 'java/lang/Object'");
 424             }
 425         }
 426         if (interfaces != null) {
 427             for (int i = 0; i < interfaces.length; ++i) {
 428                 CheckMethodAdapter.checkInternalName(interfaces[i],
 429                         "interface name at index " + i);
 430             }
 431         }
 432         this.version = version;
 433         super.visit(version, access, name, signature, superName, interfaces);
 434     }
 435 
 436     @Override
 437     public void visitSource(final String file, final String debug) {
 438         checkState();
 439         if (source) {
 440             throw new IllegalStateException(
 441                     "visitSource can be called only once.");
 442         }
 443         source = true;
 444         super.visitSource(file, debug);
 445     }
 446 
 447     @Override
 448     public void visitOuterClass(final String owner, final String name,
 449             final String desc) {
 450         checkState();
 451         if (outer) {
 452             throw new IllegalStateException(
 453                     "visitOuterClass can be called only once.");
 454         }
 455         outer = true;
 456         if (owner == null) {
 457             throw new IllegalArgumentException("Illegal outer class owner");
 458         }
 459         if (desc != null) {
 460             CheckMethodAdapter.checkMethodDesc(desc);
 461         }
 462         super.visitOuterClass(owner, name, desc);
 463     }
 464 
 465     @Override
 466     public void visitInnerClass(final String name, final String outerName,
 467             final String innerName, final int access) {
 468         checkState();
 469         CheckMethodAdapter.checkInternalName(name, "class name");
 470         if (outerName != null) {
 471             CheckMethodAdapter.checkInternalName(outerName, "outer class name");
 472         }
 473         if (innerName != null) {
 474             CheckMethodAdapter.checkIdentifier(innerName, "inner class name");
 475         }
 476         checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
 477                 + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
 478                 + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE
 479                 + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
 480                 + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);
 481         super.visitInnerClass(name, outerName, innerName, access);
 482     }
 483 
 484     @Override
 485     public FieldVisitor visitField(final int access, final String name,
 486             final String desc, final String signature, final Object value) {
 487         checkState();
 488         checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
 489                 + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
 490                 + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE
 491                 + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC
 492                 + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
 493         CheckMethodAdapter.checkUnqualifiedName(version, name, "field name");
 494         CheckMethodAdapter.checkDesc(desc, false);
 495         if (signature != null) {
 496             checkFieldSignature(signature);
 497         }
 498         if (value != null) {
 499             CheckMethodAdapter.checkConstant(value);
 500         }
 501         FieldVisitor av = super
 502                 .visitField(access, name, desc, signature, value);
 503         return new CheckFieldAdapter(av);
 504     }
 505 
 506     @Override
 507     public MethodVisitor visitMethod(final int access, final String name,
 508             final String desc, final String signature, final String[] exceptions) {
 509         checkState();
 510         checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
 511                 + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
 512                 + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED
 513                 + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE
 514                 + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT
 515                 + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
 516         if (!"<init>".equals(name) && !"<clinit>".equals(name)) {
 517             CheckMethodAdapter.checkMethodIdentifier(version, name,
 518                     "method name");
 519         }
 520         CheckMethodAdapter.checkMethodDesc(desc);
 521         if (signature != null) {
 522             checkMethodSignature(signature);
 523         }
 524         if (exceptions != null) {
 525             for (int i = 0; i < exceptions.length; ++i) {
 526                 CheckMethodAdapter.checkInternalName(exceptions[i],
 527                         "exception name at index " + i);
 528             }
 529         }
 530         CheckMethodAdapter cma;
 531         if (checkDataFlow) {
 532             cma = new CheckMethodAdapter(access, name, desc, super.visitMethod(
 533                     access, name, desc, signature, exceptions), labels);
 534         } else {
 535             cma = new CheckMethodAdapter(super.visitMethod(access, name, desc,
 536                     signature, exceptions), labels);
 537         }
 538         cma.version = version;
 539         return cma;
 540     }
 541 
 542     @Override
 543     public AnnotationVisitor visitAnnotation(final String desc,
 544             final boolean visible) {
 545         checkState();
 546         CheckMethodAdapter.checkDesc(desc, false);
 547         return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
 548     }
 549 
 550     @Override
 551     public AnnotationVisitor visitTypeAnnotation(final int typeRef,
 552             final TypePath typePath, final String desc, final boolean visible) {
 553         checkState();
 554         int sort = typeRef >>> 24;
 555         if (sort != TypeReference.CLASS_TYPE_PARAMETER
 556                 && sort != TypeReference.CLASS_TYPE_PARAMETER_BOUND
 557                 && sort != TypeReference.CLASS_EXTENDS) {
 558             throw new IllegalArgumentException("Invalid type reference sort 0x"
 559                     + Integer.toHexString(sort));
 560         }
 561         checkTypeRefAndPath(typeRef, typePath);
 562         CheckMethodAdapter.checkDesc(desc, false);
 563         return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
 564                 typePath, desc, visible));
 565     }
 566 
 567     @Override
 568     public void visitAttribute(final Attribute attr) {
 569         checkState();
 570         if (attr == null) {
 571             throw new IllegalArgumentException(
 572                     "Invalid attribute (must not be null)");
 573         }
 574         super.visitAttribute(attr);
 575     }
 576 
 577     @Override
 578     public void visitEnd() {
 579         checkState();
 580         end = true;
 581         super.visitEnd();
 582     }
 583 
 584     // ------------------------------------------------------------------------
 585     // Utility methods
 586     // ------------------------------------------------------------------------
 587 
 588     /**
 589      * Checks that the visit method has been called and that visitEnd has not
 590      * been called.
 591      */
 592     private void checkState() {
 593         if (!start) {
 594             throw new IllegalStateException(
 595                     "Cannot visit member before visit has been called.");
 596         }
 597         if (end) {
 598             throw new IllegalStateException(
 599                     "Cannot visit member after visitEnd has been called.");
 600         }
 601     }
 602 
 603     /**
 604      * Checks that the given access flags do not contain invalid flags. This
 605      * method also checks that mutually incompatible flags are not set
 606      * simultaneously.
 607      *
 608      * @param access
 609      *            the access flags to be checked
 610      * @param possibleAccess
 611      *            the valid access flags.
 612      */
 613     static void checkAccess(final int access, final int possibleAccess) {
 614         if ((access & ~possibleAccess) != 0) {
 615             throw new IllegalArgumentException("Invalid access flags: "
 616                     + access);
 617         }
 618         int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;
 619         int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;
 620         int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;
 621         if (pub + pri + pro > 1) {
 622             throw new IllegalArgumentException(
 623                     "public private and protected are mutually exclusive: "
 624                             + access);
 625         }
 626         int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;
 627         int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;
 628         if (fin + abs > 1) {
 629             throw new IllegalArgumentException(
 630                     "final and abstract are mutually exclusive: " + access);
 631         }
 632     }
 633 
 634     /**
 635      * Checks a class signature.
 636      *
 637      * @param signature
 638      *            a string containing the signature that must be checked.
 639      */
 640     public static void checkClassSignature(final String signature) {
 641         // ClassSignature:
 642         // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
 643 
 644         int pos = 0;
 645         if (getChar(signature, 0) == '<') {
 646             pos = checkFormalTypeParameters(signature, pos);
 647         }
 648         pos = checkClassTypeSignature(signature, pos);
 649         while (getChar(signature, pos) == 'L') {
 650             pos = checkClassTypeSignature(signature, pos);
 651         }
 652         if (pos != signature.length()) {
 653             throw new IllegalArgumentException(signature + ": error at index "
 654                     + pos);
 655         }
 656     }
 657 
 658     /**
 659      * Checks a method signature.
 660      *
 661      * @param signature
 662      *            a string containing the signature that must be checked.
 663      */
 664     public static void checkMethodSignature(final String signature) {
 665         // MethodTypeSignature:
 666         // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
 667         // ^ClassTypeSignature | ^TypeVariableSignature )*
 668 
 669         int pos = 0;
 670         if (getChar(signature, 0) == '<') {
 671             pos = checkFormalTypeParameters(signature, pos);
 672         }
 673         pos = checkChar('(', signature, pos);
 674         while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
 675             pos = checkTypeSignature(signature, pos);
 676         }
 677         pos = checkChar(')', signature, pos);
 678         if (getChar(signature, pos) == 'V') {
 679             ++pos;
 680         } else {
 681             pos = checkTypeSignature(signature, pos);
 682         }
 683         while (getChar(signature, pos) == '^') {
 684             ++pos;
 685             if (getChar(signature, pos) == 'L') {
 686                 pos = checkClassTypeSignature(signature, pos);
 687             } else {
 688                 pos = checkTypeVariableSignature(signature, pos);
 689             }
 690         }
 691         if (pos != signature.length()) {
 692             throw new IllegalArgumentException(signature + ": error at index "
 693                     + pos);
 694         }
 695     }
 696 
 697     /**
 698      * Checks a field signature.
 699      *
 700      * @param signature
 701      *            a string containing the signature that must be checked.
 702      */
 703     public static void checkFieldSignature(final String signature) {
 704         int pos = checkFieldTypeSignature(signature, 0);
 705         if (pos != signature.length()) {
 706             throw new IllegalArgumentException(signature + ": error at index "
 707                     + pos);
 708         }
 709     }
 710 
 711     /**
 712      * Checks the reference to a type in a type annotation.
 713      *
 714      * @param typeRef
 715      *            a reference to an annotated type.
 716      * @param typePath
 717      *            the path to the annotated type argument, wildcard bound, array
 718      *            element type, or static inner type within 'typeRef'. May be
 719      *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.
 720      */
 721     static void checkTypeRefAndPath(int typeRef, TypePath typePath) {
 722         int mask = 0;
 723         switch (typeRef >>> 24) {
 724         case TypeReference.CLASS_TYPE_PARAMETER:
 725         case TypeReference.METHOD_TYPE_PARAMETER:
 726         case TypeReference.METHOD_FORMAL_PARAMETER:
 727             mask = 0xFFFF0000;
 728             break;
 729         case TypeReference.FIELD:
 730         case TypeReference.METHOD_RETURN:
 731         case TypeReference.METHOD_RECEIVER:
 732         case TypeReference.LOCAL_VARIABLE:
 733         case TypeReference.RESOURCE_VARIABLE:
 734         case TypeReference.INSTANCEOF:
 735         case TypeReference.NEW:
 736         case TypeReference.CONSTRUCTOR_REFERENCE:
 737         case TypeReference.METHOD_REFERENCE:
 738             mask = 0xFF000000;
 739             break;
 740         case TypeReference.CLASS_EXTENDS:
 741         case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
 742         case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
 743         case TypeReference.THROWS:
 744         case TypeReference.EXCEPTION_PARAMETER:
 745             mask = 0xFFFFFF00;
 746             break;
 747         case TypeReference.CAST:
 748         case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
 749         case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
 750         case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
 751         case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
 752             mask = 0xFF0000FF;
 753             break;
 754         default:
 755             throw new IllegalArgumentException("Invalid type reference sort 0x"
 756                     + Integer.toHexString(typeRef >>> 24));
 757         }
 758         if ((typeRef & ~mask) != 0) {
 759             throw new IllegalArgumentException("Invalid type reference 0x"
 760                     + Integer.toHexString(typeRef));
 761         }
 762         if (typePath != null) {
 763             for (int i = 0; i < typePath.getLength(); ++i) {
 764                 int step = typePath.getStep(i);
 765                 if (step != TypePath.ARRAY_ELEMENT
 766                         && step != TypePath.INNER_TYPE
 767                         && step != TypePath.TYPE_ARGUMENT
 768                         && step != TypePath.WILDCARD_BOUND) {
 769                     throw new IllegalArgumentException(
 770                             "Invalid type path step " + i + " in " + typePath);
 771                 }
 772                 if (step != TypePath.TYPE_ARGUMENT
 773                         && typePath.getStepArgument(i) != 0) {
 774                     throw new IllegalArgumentException(
 775                             "Invalid type path step argument for step " + i
 776                                     + " in " + typePath);
 777                 }
 778             }
 779         }
 780     }
 781 
 782     /**
 783      * Checks the formal type parameters of a class or method signature.
 784      *
 785      * @param signature
 786      *            a string containing the signature that must be checked.
 787      * @param pos
 788      *            index of first character to be checked.
 789      * @return the index of the first character after the checked part.
 790      */
 791     private static int checkFormalTypeParameters(final String signature, int pos) {
 792         // FormalTypeParameters:
 793         // < FormalTypeParameter+ >
 794 
 795         pos = checkChar('<', signature, pos);
 796         pos = checkFormalTypeParameter(signature, pos);
 797         while (getChar(signature, pos) != '>') {
 798             pos = checkFormalTypeParameter(signature, pos);
 799         }
 800         return pos + 1;
 801     }
 802 
 803     /**
 804      * Checks a formal type parameter of a class or method signature.
 805      *
 806      * @param signature
 807      *            a string containing the signature that must be checked.
 808      * @param pos
 809      *            index of first character to be checked.
 810      * @return the index of the first character after the checked part.
 811      */
 812     private static int checkFormalTypeParameter(final String signature, int pos) {
 813         // FormalTypeParameter:
 814         // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
 815 
 816         pos = checkIdentifier(signature, pos);
 817         pos = checkChar(':', signature, pos);
 818         if ("L[T".indexOf(getChar(signature, pos)) != -1) {
 819             pos = checkFieldTypeSignature(signature, pos);
 820         }
 821         while (getChar(signature, pos) == ':') {
 822             pos = checkFieldTypeSignature(signature, pos + 1);
 823         }
 824         return pos;
 825     }
 826 
 827     /**
 828      * Checks a field type signature.
 829      *
 830      * @param signature
 831      *            a string containing the signature that must be checked.
 832      * @param pos
 833      *            index of first character to be checked.
 834      * @return the index of the first character after the checked part.
 835      */
 836     private static int checkFieldTypeSignature(final String signature, int pos) {
 837         // FieldTypeSignature:
 838         // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
 839         //
 840         // ArrayTypeSignature:
 841         // [ TypeSignature
 842 
 843         switch (getChar(signature, pos)) {
 844         case 'L':
 845             return checkClassTypeSignature(signature, pos);
 846         case '[':
 847             return checkTypeSignature(signature, pos + 1);
 848         default:
 849             return checkTypeVariableSignature(signature, pos);
 850         }
 851     }
 852 
 853     /**
 854      * Checks a class type signature.
 855      *
 856      * @param signature
 857      *            a string containing the signature that must be checked.
 858      * @param pos
 859      *            index of first character to be checked.
 860      * @return the index of the first character after the checked part.
 861      */
 862     private static int checkClassTypeSignature(final String signature, int pos) {
 863         // ClassTypeSignature:
 864         // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
 865         // TypeArguments? )* ;
 866 
 867         pos = checkChar('L', signature, pos);
 868         pos = checkIdentifier(signature, pos);
 869         while (getChar(signature, pos) == '/') {
 870             pos = checkIdentifier(signature, pos + 1);
 871         }
 872         if (getChar(signature, pos) == '<') {
 873             pos = checkTypeArguments(signature, pos);
 874         }
 875         while (getChar(signature, pos) == '.') {
 876             pos = checkIdentifier(signature, pos + 1);
 877             if (getChar(signature, pos) == '<') {
 878                 pos = checkTypeArguments(signature, pos);
 879             }
 880         }
 881         return checkChar(';', signature, pos);
 882     }
 883 
 884     /**
 885      * Checks the type arguments in a class type signature.
 886      *
 887      * @param signature
 888      *            a string containing the signature that must be checked.
 889      * @param pos
 890      *            index of first character to be checked.
 891      * @return the index of the first character after the checked part.
 892      */
 893     private static int checkTypeArguments(final String signature, int pos) {
 894         // TypeArguments:
 895         // < TypeArgument+ >
 896 
 897         pos = checkChar('<', signature, pos);
 898         pos = checkTypeArgument(signature, pos);
 899         while (getChar(signature, pos) != '>') {
 900             pos = checkTypeArgument(signature, pos);
 901         }
 902         return pos + 1;
 903     }
 904 
 905     /**
 906      * Checks a type argument in a class type signature.
 907      *
 908      * @param signature
 909      *            a string containing the signature that must be checked.
 910      * @param pos
 911      *            index of first character to be checked.
 912      * @return the index of the first character after the checked part.
 913      */
 914     private static int checkTypeArgument(final String signature, int pos) {
 915         // TypeArgument:
 916         // * | ( ( + | - )? FieldTypeSignature )
 917 
 918         char c = getChar(signature, pos);
 919         if (c == '*') {
 920             return pos + 1;
 921         } else if (c == '+' || c == '-') {
 922             pos++;
 923         }
 924         return checkFieldTypeSignature(signature, pos);
 925     }
 926 
 927     /**
 928      * Checks a type variable signature.
 929      *
 930      * @param signature
 931      *            a string containing the signature that must be checked.
 932      * @param pos
 933      *            index of first character to be checked.
 934      * @return the index of the first character after the checked part.
 935      */
 936     private static int checkTypeVariableSignature(final String signature,
 937             int pos) {
 938         // TypeVariableSignature:
 939         // T Identifier ;
 940 
 941         pos = checkChar('T', signature, pos);
 942         pos = checkIdentifier(signature, pos);
 943         return checkChar(';', signature, pos);
 944     }
 945 
 946     /**
 947      * Checks a type signature.
 948      *
 949      * @param signature
 950      *            a string containing the signature that must be checked.
 951      * @param pos
 952      *            index of first character to be checked.
 953      * @return the index of the first character after the checked part.
 954      */
 955     private static int checkTypeSignature(final String signature, int pos) {
 956         // TypeSignature:
 957         // Z | C | B | S | I | F | J | D | FieldTypeSignature
 958 
 959         switch (getChar(signature, pos)) {
 960         case 'Z':
 961         case 'C':
 962         case 'B':
 963         case 'S':
 964         case 'I':
 965         case 'F':
 966         case 'J':
 967         case 'D':
 968             return pos + 1;
 969         default:
 970             return checkFieldTypeSignature(signature, pos);
 971         }
 972     }
 973 
 974     /**
 975      * Checks an identifier.
 976      *
 977      * @param signature
 978      *            a string containing the signature that must be checked.
 979      * @param pos
 980      *            index of first character to be checked.
 981      * @return the index of the first character after the checked part.
 982      */
 983     private static int checkIdentifier(final String signature, int pos) {
 984         if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
 985             throw new IllegalArgumentException(signature
 986                     + ": identifier expected at index " + pos);
 987         }
 988         ++pos;
 989         while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
 990             ++pos;
 991         }
 992         return pos;
 993     }
 994 
 995     /**
 996      * Checks a single character.
 997      *
 998      * @param signature
 999      *            a string containing the signature that must be checked.
1000      * @param pos
1001      *            index of first character to be checked.
1002      * @return the index of the first character after the checked part.
1003      */
1004     private static int checkChar(final char c, final String signature, int pos) {
1005         if (getChar(signature, pos) == c) {
1006             return pos + 1;
1007         }
1008         throw new IllegalArgumentException(signature + ": '" + c
1009                 + "' expected at index " + pos);
1010     }
1011 
1012     /**
1013      * Returns the signature car at the given index.
1014      *
1015      * @param signature
1016      *            a signature.
1017      * @param pos
1018      *            an index in signature.
1019      * @return the character at the given index, or 0 if there is no such
1020      *         character.
1021      */
1022     private static char getChar(final String signature, int pos) {
1023         return pos < signature.length() ? signature.charAt(pos) : (char) 0;
1024     }
1025 }