< prev index next >

src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java

Print this page
rev 47452 : imported patch jdk-new-asmv6.patch


  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>


 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.


 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      * @throws IllegalStateException
 363      *             If a subclass calls this constructor.
 364      */
 365     public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) {
 366         this(Opcodes.ASM5, cv, checkDataFlow);
 367         if (getClass() != CheckClassAdapter.class) {
 368             throw new IllegalStateException();
 369         }
 370     }
 371 
 372     /**
 373      * Constructs a new {@link CheckClassAdapter}.
 374      *
 375      * @param api
 376      *            the ASM API version implemented by this visitor. Must be one
 377      *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
 378      * @param cv
 379      *            the class visitor to which this adapter must delegate calls.
 380      * @param checkDataFlow
 381      *            <tt>true</tt> to perform basic data flow checks, or
 382      *            <tt>false</tt> to not perform any data flow check (see
 383      *            {@link CheckMethodAdapter}). This option requires valid
 384      *            maxLocals and maxStack values.
 385      */
 386     protected CheckClassAdapter(final int api, final ClassVisitor cv,
 387             final boolean checkDataFlow) {
 388         super(api, cv);
 389         this.labels = new HashMap<Label, Integer>();
 390         this.checkDataFlow = checkDataFlow;
 391     }
 392 
 393     // ------------------------------------------------------------------------
 394     // Implementation of the ClassVisitor interface
 395     // ------------------------------------------------------------------------
 396 
 397     @Override
 398     public void visit(final int version, final int access, final String name,
 399             final String signature, final String superName,
 400             final String[] interfaces) {
 401         if (start) {
 402             throw new IllegalStateException("visit must be called only once");
 403         }
 404         start = true;
 405         checkState();
 406         checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
 407                 + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
 408                 + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
 409                 + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
 410                 + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
 411         if (name == null || !name.endsWith("package-info")) {




 412             CheckMethodAdapter.checkInternalName(name, "class name");
 413         }
 414         if ("java/lang/Object".equals(name)) {
 415             if (superName != null) {
 416                 throw new IllegalArgumentException(
 417                         "The super class name of the Object class must be 'null'");
 418             }
 419         } else {
 420             CheckMethodAdapter.checkInternalName(superName, "super class name");
 421         }
 422         if (signature != null) {
 423             checkClassSignature(signature);
 424         }
 425         if ((access & Opcodes.ACC_INTERFACE) != 0) {
 426             if (!"java/lang/Object".equals(superName)) {
 427                 throw new IllegalArgumentException(
 428                         "The super class name of interfaces must be 'java/lang/Object'");
 429             }
 430         }
 431         if (interfaces != null) {
 432             for (int i = 0; i < interfaces.length; ++i) {
 433                 CheckMethodAdapter.checkInternalName(interfaces[i],
 434                         "interface name at index " + i);
 435             }
 436         }
 437         this.version = version;
 438         super.visit(version, access, name, signature, superName, interfaces);
 439     }
 440 
 441     @Override
 442     public void visitSource(final String file, final String debug) {
 443         checkState();
 444         if (source) {
 445             throw new IllegalStateException(
 446                     "visitSource can be called only once.");
 447         }
 448         source = true;
 449         super.visitSource(file, debug);
 450     }
 451 
















 452     @Override
 453     public void visitOuterClass(final String owner, final String name,
 454             final String desc) {
 455         checkState();
 456         if (outer) {
 457             throw new IllegalStateException(
 458                     "visitOuterClass can be called only once.");
 459         }
 460         outer = true;
 461         if (owner == null) {
 462             throw new IllegalArgumentException("Illegal outer class owner");
 463         }
 464         if (desc != null) {
 465             CheckMethodAdapter.checkMethodDesc(desc);
 466         }
 467         super.visitOuterClass(owner, name, desc);
 468     }
 469 
 470     @Override
 471     public void visitInnerClass(final String name, final String outerName,




  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>


 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.


 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,


< prev index next >