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