8375433: jar should validate automatic module names

Reviewed-by: jvernee
This commit is contained in:
Christian Stein 2026-01-28 15:02:21 +00:00
parent 8c86b1bb10
commit 8095e33ee8
3 changed files with 83 additions and 9 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,6 +47,8 @@ import java.util.function.Function;
import java.util.function.IntSupplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
@ -100,6 +102,7 @@ final class Validator {
this.zf = zf;
this.zis = zis;
checkModuleDescriptor(MODULE_INFO);
checkAutomaticModuleName();
}
static boolean validate(Main main, File zipFile) throws IOException {
@ -453,6 +456,36 @@ final class Validator {
});
}
/**
* Checks whether an Automatic-Module-Name entry is valid
* and also verifies it to the name given by a compiled
* module descriptor.
*/
private void checkAutomaticModuleName() {
var entry = zf.getEntry("META-INF/MANIFEST.MF");
if (entry == null) {
return;
}
try (InputStream jis = zf.getInputStream(entry)) {
Attributes attributes = new Manifest(jis).getMainAttributes();
String automaticModuleName = attributes.getValue("Automatic-Module-Name");
if (automaticModuleName == null) {
return;
}
try {
ModuleDescriptor.newAutomaticModule(automaticModuleName);
} catch (IllegalArgumentException e) {
errorAndInvalid(formatMsg("error.validator.manifest.invalid.automatic.module.name", automaticModuleName));
}
if (md == null || automaticModuleName.equals(md.name())) {
return;
}
errorAndInvalid(formatMsg("error.validator.manifest.inconsistent.automatic.module.name", automaticModuleName, md.name()));
} catch (IOException e) {
errorAndInvalid(e.getMessage());
}
}
/*
* Checks whether or not the given versioned module descriptor's attributes
* are valid when compared against the root/base module descriptor.

View File

@ -138,6 +138,10 @@ error.validator.metainf.wrong.position=\
expected entry META-INF/ to be at position 0, but found: {0}
error.validator.manifest.wrong.position=\
expected entry META-INF/MANIFEST.MF to be at position 0 or 1, but found it at position: {0}
error.validator.manifest.invalid.automatic.module.name=\
invalid module name of Automatic-Module-Name entry in manifest: {0}
error.validator.manifest.inconsistent.automatic.module.name=\
expected Automatic-Module-Name entry in manifest: {0} to match name of compiled module: {1}
warn.validator.identical.entry=\
Warning: entry {0} contains a class that\n\
is identical to an entry already in the jar

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,12 +23,8 @@
/*
* @test
* @bug 8345431
* @bug 8345431 8375433
* @summary test validator to report malformed jar file
* @library /test/lib
* @modules jdk.jartool
* @build jdk.test.lib.Platform
* jdk.test.lib.util.FileUtils
* @run junit/othervm ValidatorTest
*/
@ -40,6 +36,7 @@ import org.junit.jupiter.api.TestInstance.Lifecycle;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertLinesMatch;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@ -59,13 +56,15 @@ import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import jdk.test.lib.util.FileUtils;
class ValidatorTest {
private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
.orElseThrow(() ->
new RuntimeException("jar tool not found")
);
private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
.orElseThrow(() ->
new RuntimeException("javac tool not found")
);
private final String nl = System.lineSeparator();
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
@ -310,6 +309,44 @@ class ValidatorTest {
}
}
@Test
public void testInvalidAutomaticModuleName() throws Exception {
System.out.printf("%n%n*****Creating Jar with invalid Automatic-Module-Name in Manifest*****%n%n");
var file = Path.of("InvalidAutomaticModuleName.jar");
var manifest = Path.of("MANIFEST.MF");
Files.writeString(manifest,
"""
Automatic-Module-Name: default
""");
jar("--create --file " + file + " --manifest " + manifest);
var e = assertThrows(IOException.class, () -> jar("--validate --file " + file.toString()));
var err = e.getMessage();
System.out.println(err);
assertTrue(err.contains("invalid module name of Automatic-Module-Name entry in manifest: default"), "missing warning for: default");
}
@Test
public void testWrongAutomaticModuleName() throws Exception {
System.out.printf("%n%n*****Creating Jar with wrong Automatic-Module-Name in Manifest*****%n%n");
var file = Path.of("WrongAutomaticModuleName.jar");
var foo = Path.of("module-info.java");
Files.writeString(foo,
"""
module foo {}
""");
var manifest = Path.of("MANIFEST.MF");
Files.writeString(manifest,
"""
Automatic-Module-Name: bar
""");
JAVAC_TOOL.run(System.out, System.err, foo.toString());
jar("--create --file " + file + " --manifest " + manifest + " module-info.class");
var e = assertThrows(IOException.class, () -> jar("--validate --file " + file.toString()));
var err = e.getMessage();
System.out.println(err);
assertTrue(err.contains("expected Automatic-Module-Name entry in manifest: bar to match name of compiled module: foo"), "missing warning for: foo/bar");
}
/**
* Validates that base manifest-related entries are at expected LOC positions.
* <p>