1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import jdk.internal.org.objectweb.asm.*;
  25 
  26 /*
  27  * @test
  28  * @summary Test scenarios for constant pool CONSTANT_Module and CONSTANT_Package
  29  *          types, for class file versions 53 and 52, when ACC_MODULE is set and
  30  *          not set in the access_flags.
  31  * @bug 8175383
  32  * @library /test/lib
  33  * @modules java.base/jdk.internal.org.objectweb.asm
  34  * @compile -XDignore.symbol.file ConstModule.java
  35  * @run main ConstModule
  36  */
  37 
  38 public class ConstModule {
  39 
  40     static final int ACC_MODULE = 0x8000;
  41     static final boolean MODULE_TEST = true;
  42     static final boolean PACKAGE_TEST = false;
  43     static final boolean CFE_EXCEPTION = true;
  44     static final boolean NCDFE_EXCEPTION = false;
  45 
  46     public static void main(String[] args) throws Exception {
  47 
  48         // Test that the JVM throws CFE for constant pool CONSTANT_Module type, for
  49         // class file version 53, when ACC_MODULE is not set in the access_flags.
  50         ConstModule.write_and_load(Opcodes.V9,
  51             Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC,
  52             "jdk.fooMod", "FooMod", MODULE_TEST, CFE_EXCEPTION);
  53 
  54         // Test that the JVM throws NCDFE for constant pool CONSTANT_Module type,
  55         // for class file version 53, when ACC_MODULE is set in the access_flags.
  56         ConstModule.write_and_load(Opcodes.V9,
  57             Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE,
  58             "jdk.fooModACC", "FooModACC", MODULE_TEST, NCDFE_EXCEPTION);
  59 
  60         // Test that the JVM throws CFE for constant pool CONSTANT_Module type, for
  61         // class file version 52, even when ACC_MODULE is set in the access_flags.
  62         ConstModule.write_and_load(Opcodes.V1_8,
  63             Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE,
  64             "jdk.fooModACC52", "FooModACC52", MODULE_TEST, CFE_EXCEPTION);
  65 
  66         // Test that the JVM throws CFE for constant pool CONSTANT_Package type, for
  67         // class file version 53, when ACC_MODULE is not set in the access_flags.
  68         ConstModule.write_and_load(Opcodes.V9,
  69             Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC,
  70             "jdk.fooPkg", "FooPkg", PACKAGE_TEST, CFE_EXCEPTION);
  71 
  72         // Test that the JVM throws NCDFE for constant pool CONSTANT_Package type,
  73         // for class file version 53, when ACC_MODULE is set in the access_flags.
  74         ConstModule.write_and_load(Opcodes.V9,
  75             Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE,
  76             "jdk.fooModACC", "FooModACC", PACKAGE_TEST, NCDFE_EXCEPTION);
  77 
  78         // Test that the JVM throws CFE for constant pool CONSTANT_Package type, for
  79         // class file version 52, even when ACC_MODULE is set in the access_flags.
  80         ConstModule.write_and_load(Opcodes.V1_8,
  81             Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE,
  82             "jdk.fooModACC52", "FooModACC52", PACKAGE_TEST, CFE_EXCEPTION);
  83 
  84     }
  85 
  86     public static void write_and_load(int version,
  87                                       int access_flags,
  88                                       String attr,
  89                                       String class_name,
  90                                       boolean module_test,
  91                                       boolean throwCFE) throws Exception {
  92         ClassWriter cw = new ClassWriter(0);
  93         cw.visit(version,
  94                  access_flags,
  95                  class_name,
  96                  null,
  97                  "java/lang/Object",
  98                  null);
  99 
 100         if (module_test)
 101             cw.visitAttribute(new TestModuleAttribute(attr));
 102         else
 103             cw.visitAttribute(new TestPackageAttribute(attr));
 104 
 105         cw.visitEnd();
 106         byte[] bytes = cw.toByteArray();
 107 
 108 
 109         ClassLoader loader = new ClassLoader(ConstModule.class.getClassLoader()) {
 110             @Override
 111             protected Class<?> findClass(String cn)throws ClassNotFoundException {
 112                 if (cn.equals(class_name)) {
 113                     try {
 114                         Class superClass = super.defineClass(cn, bytes, 0, bytes.length);
 115                         throw new RuntimeException("Expected ClassFormatError not thrown");
 116                     } catch (java.lang.ClassFormatError e) {
 117                        if (!throwCFE) {
 118                            throw new RuntimeException("Unexpected ClassFormatError exception: " + e.getMessage());
 119                        }
 120                        if (module_test && !e.getMessage().contains(
 121                            "Unknown constant tag 19 in class file")) {
 122                            throw new RuntimeException("Wrong ClassFormatError exception: " + e.getMessage());
 123                        } else if (!module_test && !e.getMessage().contains(
 124                            "Unknown constant tag 20 in class file")) {
 125                            throw new RuntimeException("Wrong ClassFormatError exception: " + e.getMessage());
 126                        }
 127                     } catch (java.lang.NoClassDefFoundError f) {
 128                        if (throwCFE) {
 129                            throw new RuntimeException("Unexpected NoClassDefFoundError exception: " + f.getMessage());
 130                        }
 131                        if (!f.getMessage().contains(
 132                            "is not a class because access_flag ACC_MODULE is set")) {
 133                            throw new RuntimeException("Wrong NoClassDefFoundError exception: " + f.getMessage());
 134                        }
 135                     }
 136                 } else {
 137                     throw new ClassNotFoundException(cn);
 138                 }
 139                 return null;
 140             }
 141         };
 142 
 143         Class<?> clazz = loader.loadClass(class_name);
 144     }
 145 
 146     /**
 147      * ConstModuleAttr attribute.
 148      *
 149      * <pre> {@code
 150      *
 151      * MainClass_attribute {
 152      *   // index to CONSTANT_utf8_info structure in constant pool representing
 153      *   // the string "ConstModuleAttr"
 154      *   u2 attribute_name_index;
 155      *   u4 attribute_length;
 156      *
 157      *   // index to CONSTANT_Module_info structure
 158      *   u2 module_name_index
 159      * }
 160      *
 161      * } </pre>
 162      */
 163     public static class TestModuleAttribute extends Attribute {
 164         private final String moduleName;
 165 
 166         public TestModuleAttribute(String moduleName) {
 167             super("ConstModuleAttr");
 168             this.moduleName = moduleName;
 169         }
 170 
 171         public TestModuleAttribute() {
 172             this(null);
 173         }
 174 
 175         @Override
 176         protected Attribute read(ClassReader cr,
 177                                  int off,
 178                                  int len,
 179                                  char[] buf,
 180                                  int codeOff,
 181                                  Label[] labels)
 182         {
 183             String mn = cr.readModule(off, buf);
 184             off += 2;
 185             return new TestModuleAttribute(mn);
 186         }
 187 
 188         @Override
 189         protected ByteVector write(ClassWriter cw,
 190                                    byte[] code,
 191                                    int len,
 192                                    int maxStack,
 193                                    int maxLocals)
 194         {
 195             ByteVector attr = new ByteVector();
 196             attr.putShort(cw.newModule(moduleName));
 197             return attr;
 198         }
 199     }
 200 
 201     /**
 202      * ConstPackageAttr attribute.
 203      *
 204      * <pre> {@code
 205      *
 206      * MainClass_attribute {
 207      *   // index to CONSTANT_utf8_info structure in constant pool representing
 208      *   // the string "ConstPackageAttr"
 209      *   u2 attribute_name_index;
 210      *   u4 attribute_length;
 211      *
 212      *   // index to CONSTANT_Package_info structure
 213      *   u2 module_name_index
 214      * }
 215      *
 216      * } </pre>
 217      */
 218     public static class TestPackageAttribute extends Attribute {
 219         private final String packageName;
 220 
 221         public TestPackageAttribute(String packageName) {
 222             super("ConstPackageAttr");
 223             this.packageName = packageName;
 224         }
 225 
 226         public TestPackageAttribute() {
 227             this(null);
 228         }
 229 
 230         @Override
 231         protected Attribute read(ClassReader cr,
 232                                  int off,
 233                                  int len,
 234                                  char[] buf,
 235                                  int codeOff,
 236                                  Label[] labels)
 237         {
 238             String mn = cr.readPackage(off, buf);
 239             off += 2;
 240             return new TestPackageAttribute(mn);
 241         }
 242 
 243         @Override
 244         protected ByteVector write(ClassWriter cw,
 245                                    byte[] code,
 246                                    int len,
 247                                    int maxStack,
 248                                    int maxLocals)
 249         {
 250             ByteVector attr = new ByteVector();
 251             attr.putShort(cw.newPackage(packageName));
 252             return attr;
 253         }
 254     }
 255 }