8300228: ModuleReader.find on exploded module throws if resource name maps to invalid file path

Reviewed-by: jpai, chegar, cstein
This commit is contained in:
Alan Bateman 2023-01-17 16:25:11 +00:00
parent 4cd166ff27
commit fb147aaea1
2 changed files with 43 additions and 26 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.FileSystem; import java.nio.file.FileSystem;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
@ -132,15 +133,24 @@ public final class Resources {
return null; return null;
} }
// convert to file path // map resource name to a file path string
Path path; String pathString;
if (File.separatorChar == '/') { if (File.separatorChar == '/') {
path = fs.getPath(name); pathString = name;
} else { } else {
// not allowed to embed file separators // not allowed to embed file separators
if (name.contains(File.separator)) if (name.contains(File.separator))
return null; return null;
path = fs.getPath(name.replace('/', File.separatorChar)); pathString = name.replace('/', File.separatorChar);
}
// try to convert to a Path
Path path;
try {
path = fs.getPath(pathString);
} catch (InvalidPathException e) {
// not a valid file path
return null;
} }
// file path not allowed to have root component // file path not allowed to have root component

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,6 +23,7 @@
/** /**
* @test * @test
* @bug 8142968 8300228
* @library /test/lib * @library /test/lib
* @modules java.base/jdk.internal.module * @modules java.base/jdk.internal.module
* jdk.compiler * jdk.compiler
@ -64,9 +65,7 @@ import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static org.testng.Assert.*; import static org.testng.Assert.*;
@Test
public class ModuleReaderTest { public class ModuleReaderTest {
private static final String TEST_SRC = System.getProperty("test.src"); private static final String TEST_SRC = System.getProperty("test.src");
private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
@ -110,6 +109,12 @@ public class ModuleReaderTest {
"../java/lang/Object.class", "../java/lang/Object.class",
"java/../lang/Object.class", "java/../lang/Object.class",
"java/lang/../Object.class", "java/lang/../Object.class",
// junk resource names
"java\u0000",
"C:java",
"C:\\java",
"java\\lang\\Object.class"
}; };
// resources in test module (can't use module-info.class as a test // resources in test module (can't use module-info.class as a test
@ -136,26 +141,28 @@ public class ModuleReaderTest {
"./p/Main.class", "./p/Main.class",
"p/./Main.class", "p/./Main.class",
"../p/Main.class", "../p/Main.class",
"p/../p/Main.class" "p/../p/Main.class",
};
// junk resource names
"p\u0000",
"C:p",
"C:\\p",
"p\\Main.class"
};
@BeforeTest @BeforeTest
public void compileTestModule() throws Exception { public void compileTestModule() throws Exception {
// javac -d mods/$TESTMODULE src/$TESTMODULE/** // javac -d mods/$TESTMODULE src/$TESTMODULE/**
boolean compiled boolean compiled = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
= CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE), MODS_DIR.resolve(TEST_MODULE));
MODS_DIR.resolve(TEST_MODULE));
assertTrue(compiled, "test module did not compile"); assertTrue(compiled, "test module did not compile");
} }
/** /**
* Test ModuleReader to module in runtime image * Test ModuleReader with module in runtime image.
*/ */
@Test
public void testImage() throws IOException { public void testImage() throws IOException {
ModuleFinder finder = ModuleFinder.ofSystem(); ModuleFinder finder = ModuleFinder.ofSystem();
ModuleReference mref = finder.find(BASE_MODULE).get(); ModuleReference mref = finder.find(BASE_MODULE).get();
ModuleReader reader = mref.open(); ModuleReader reader = mref.open();
@ -227,18 +234,18 @@ public class ModuleReaderTest {
} catch (IOException expected) { } } catch (IOException expected) { }
} }
/** /**
* Test ModuleReader to exploded module * Test ModuleReader with exploded module.
*/ */
@Test
public void testExplodedModule() throws IOException { public void testExplodedModule() throws IOException {
test(MODS_DIR); test(MODS_DIR);
} }
/** /**
* Test ModuleReader to modular JAR * Test ModuleReader with module in modular JAR.
*/ */
@Test
public void testModularJar() throws IOException { public void testModularJar() throws IOException {
Path dir = Files.createTempDirectory(USER_DIR, "mlib"); Path dir = Files.createTempDirectory(USER_DIR, "mlib");
@ -249,10 +256,10 @@ public class ModuleReaderTest {
test(dir); test(dir);
} }
/** /**
* Test ModuleReader to JMOD * Test ModuleReader with module in a JMOD file.
*/ */
@Test
public void testJMod() throws IOException { public void testJMod() throws IOException {
Path dir = Files.createTempDirectory(USER_DIR, "mlib"); Path dir = Files.createTempDirectory(USER_DIR, "mlib");
@ -269,13 +276,11 @@ public class ModuleReaderTest {
test(dir); test(dir);
} }
/** /**
* The test module is found on the given module path. Open a ModuleReader * The test module is found on the given module path. Open a ModuleReader
* to the test module and test the reader. * to the test module and test the reader.
*/ */
void test(Path mp) throws IOException { void test(Path mp) throws IOException {
ModuleFinder finder = ModulePath.of(Runtime.version(), true, mp); ModuleFinder finder = ModulePath.of(Runtime.version(), true, mp);
ModuleReference mref = finder.find(TEST_MODULE).get(); ModuleReference mref = finder.find(TEST_MODULE).get();
ModuleReader reader = mref.open(); ModuleReader reader = mref.open();
@ -284,6 +289,7 @@ public class ModuleReaderTest {
// test resources in test module // test resources in test module
for (String name : TEST_RESOURCES) { for (String name : TEST_RESOURCES) {
System.out.println("resource: " + name);
byte[] expectedBytes byte[] expectedBytes
= Files.readAllBytes(MODS_DIR = Files.readAllBytes(MODS_DIR
.resolve(TEST_MODULE) .resolve(TEST_MODULE)
@ -297,7 +303,7 @@ public class ModuleReaderTest {
// test resources that may be in the test module // test resources that may be in the test module
for (String name : MAYBE_TEST_RESOURCES) { for (String name : MAYBE_TEST_RESOURCES) {
System.out.println(name); System.out.println("resource: " + name);
Optional<URI> ouri = reader.find(name); Optional<URI> ouri = reader.find(name);
ouri.ifPresent(uri -> { ouri.ifPresent(uri -> {
if (name.endsWith("/")) if (name.endsWith("/"))
@ -307,6 +313,7 @@ public class ModuleReaderTest {
// test "not found" in test module // test "not found" in test module
for (String name : NOT_TEST_RESOURCES) { for (String name : NOT_TEST_RESOURCES) {
System.out.println("resource: " + name);
assertFalse(reader.find(name).isPresent()); assertFalse(reader.find(name).isPresent());
assertFalse(reader.open(name).isPresent()); assertFalse(reader.open(name).isPresent());
assertFalse(reader.read(name).isPresent()); assertFalse(reader.read(name).isPresent());