1 /*
2  * Copyright (c) 2017, 2018, 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 
main(String[] args)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 
write_and_load(int version, int access_flags, String attr, String class_name, boolean module_test, boolean throwCFE)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 
TestModuleAttribute(String moduleName)166         public TestModuleAttribute(String moduleName) {
167             super("ConstModuleAttr");
168             this.moduleName = moduleName;
169         }
170 
TestModuleAttribute()171         public TestModuleAttribute() {
172             this(null);
173         }
174 
175         @Override
read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels)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
write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals)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 
TestPackageAttribute(String packageName)221         public TestPackageAttribute(String packageName) {
222             super("ConstPackageAttr");
223             this.packageName = packageName;
224         }
225 
TestPackageAttribute()226         public TestPackageAttribute() {
227             this(null);
228         }
229 
230         @Override
read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels)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
write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals)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 }
256