changeset 4486:425abd8ac1eb

Reject module-info classfiles for open modules that have non-zero number of opens directives.
author jlahoda
date Mon, 28 Nov 2016 21:08:19 +0100
parents 8156e205fcb4
children dd31ba802575
files src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties test/tools/javac/diags/examples.not-yet.txt test/tools/javac/modules/OpenModulesTest.java
diffstat 4 files changed, 95 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Nov 28 13:02:49 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Nov 28 21:08:19 2016 +0100
@@ -1312,6 +1312,9 @@
                         directives.addAll(msym.exports);
                         ListBuffer<ExportsDirective> opens = new ListBuffer<>();
                         int nopens = nextChar();
+                        if (nopens != 0 && msym.flags.contains(ModuleFlags.OPEN)) {
+                            throw badClassFile("module.non.zero.opens", currentModule.name);
+                        }
                         for (int i = 0; i < nopens; i++) {
                             Name n = readName(nextChar());
                             PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Nov 28 13:02:49 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Nov 28 21:08:19 2016 +0100
@@ -2824,6 +2824,14 @@
 compiler.misc.module.name.mismatch=\
     module name {0} does not match expected name {1}
 
+# 0: name
+compiler.err.module.non.zero.opens=\
+    open module {0} has non-zero opens_count
+
+# 0: name
+compiler.misc.module.non.zero.opens=\
+    open module {0} has non-zero opens_count
+
 compiler.err.module.decl.sb.in.module-info.java=\
     module declarations should be in a file named module-info.java
 
--- a/test/tools/javac/diags/examples.not-yet.txt	Mon Nov 28 13:02:49 2016 +0100
+++ b/test/tools/javac/diags/examples.not-yet.txt	Mon Nov 28 21:08:19 2016 +0100
@@ -69,6 +69,8 @@
 compiler.misc.module.name.mismatch
 compiler.misc.no.unique.minimal.instance.exists
 compiler.misc.no.unique.maximal.instance.exists         # cannot happen?
+compiler.err.module.non.zero.opens                      # bad class file
+compiler.misc.module.non.zero.opens                     # bad class file
 compiler.misc.resume.abort                              # prompt for a response
 compiler.misc.source.unavailable                        # DiagnosticSource
 compiler.misc.token.bad-symbol
--- a/test/tools/javac/modules/OpenModulesTest.java	Mon Nov 28 13:02:49 2016 +0100
+++ b/test/tools/javac/modules/OpenModulesTest.java	Mon Nov 28 21:08:19 2016 +0100
@@ -27,16 +27,26 @@
  * @library /tools/lib
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.classfile
  *          jdk.jdeps/com.sun.tools.javap
  * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
  * @run main OpenModulesTest
  */
 
+import java.io.OutputStream;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.Attributes;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ClassWriter;
+import com.sun.tools.classfile.Module_attribute;
 import toolbox.JavacTask;
 import toolbox.JavapTask;
 import toolbox.Task;
@@ -202,4 +212,76 @@
 
     }
 
+    @Test
+    public void testNonZeroOpensInOpen(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
+        tb.writeJavaFiles(m1,
+                          "module m1 { opens api; }",
+                          "package api; public class Api {}");
+        Path classes = base.resolve("classes");
+        Path m1Classes = classes.resolve("m1");
+        tb.createDirectories(m1Classes);
+
+        new JavacTask(tb)
+            .options("-XDrawDiagnostics")
+            .outdir(m1Classes)
+            .files(findJavaFiles(m1))
+            .run(Expect.SUCCESS)
+            .writeAll();
+
+        Path miClass = m1Classes.resolve("module-info.class");
+        ClassFile cf = ClassFile.read(miClass);
+        Module_attribute module = (Module_attribute) cf.attributes.map.get(Attribute.Module);
+        Module_attribute newModule = new Module_attribute(module.attribute_name_index,
+                                                          module.module_name,
+                                                          module.module_flags | Module_attribute.ACC_OPEN,
+                                                          module.requires,
+                                                          module.exports,
+                                                          module.opens,
+                                                          module.uses_index,
+                                                          module.provides);
+        Map<String, Attribute> attrs = new HashMap<>(cf.attributes.map);
+
+        attrs.put(Attribute.Module, newModule);
+
+        Attributes newAttributes = new Attributes(attrs);
+        ClassFile newClassFile = new ClassFile(cf.magic,
+                                               cf.minor_version,
+                                               cf.major_version,
+                                               cf.constant_pool,
+                                               cf.access_flags,
+                                               cf.this_class,
+                                               cf.super_class,
+                                               cf.interfaces,
+                                               cf.fields,
+                                               cf.methods,
+                                               newAttributes);
+
+        try (OutputStream out = Files.newOutputStream(miClass)) {
+            new ClassWriter().write(newClassFile, out);
+        }
+
+        Path test = base.resolve("test");
+        tb.writeJavaFiles(test,
+                          "package impl; public class Impl extends api.Api {}");
+        Path testClasses = base.resolve("test-classes");
+        tb.createDirectories(testClasses);
+
+        List<String> log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--module-path", classes.toString(),
+                         "--add-modules", "m1")
+                .outdir(testClasses)
+                .files(findJavaFiles(test))
+                .run(Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("- compiler.err.cant.access: m1.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.module.non.zero.opens: m1))",
+                                              "1 error");
+
+        if (!expected.equals(log))
+            throw new Exception("expected output not found: " + log);
+    }
+
 }