mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
Merge branch '6.2.x'
This commit is contained in:
+11
-2
@@ -614,10 +614,12 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
private Set<ClassPathManifestEntry> getClassPathManifestEntriesFromJar(File jar) throws IOException {
|
||||
URL base = jar.toURI().toURL();
|
||||
File parent = jar.getAbsoluteFile().getParentFile();
|
||||
|
||||
try (JarFile jarFile = new JarFile(jar)) {
|
||||
Manifest manifest = jarFile.getManifest();
|
||||
Attributes attributes = (manifest != null ? manifest.getMainAttributes() : null);
|
||||
String classPath = (attributes != null ? attributes.getValue(Name.CLASS_PATH) : null);
|
||||
|
||||
Set<ClassPathManifestEntry> manifestEntries = new LinkedHashSet<>();
|
||||
if (StringUtils.hasLength(classPath)) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(classPath);
|
||||
@@ -627,8 +629,15 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
// See jdk.internal.loader.URLClassPath.JarLoader.tryResolveFile(URL, String)
|
||||
continue;
|
||||
}
|
||||
File candidate = new File(parent, path);
|
||||
if (candidate.isFile() && candidate.getCanonicalPath().contains(parent.getCanonicalPath())) {
|
||||
|
||||
// Handle absolute paths correctly: do not apply parent to absolute paths.
|
||||
File pathFile = new File(path);
|
||||
File candidate = (pathFile.isAbsolute() ? pathFile : new File(parent, path));
|
||||
|
||||
// For relative paths, enforce security check: must be under parent.
|
||||
// For absolute paths, just verify file exists (matching JVM behavior).
|
||||
if (candidate.isFile() && (pathFile.isAbsolute() ||
|
||||
candidate.getCanonicalPath().contains(parent.getCanonicalPath()))) {
|
||||
manifestEntries.add(ClassPathManifestEntry.of(candidate, this.useCaches));
|
||||
}
|
||||
}
|
||||
|
||||
+44
@@ -337,6 +337,21 @@ class PathMatchingResourcePatternResolverTests {
|
||||
assertThat(result.replace("\\", "/")).contains("!!!!").contains("/lib/asset.jar!/assets/file.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
void javaDashJarFindsAbsoluteClassPathManifestEntries() throws Exception {
|
||||
Path assetJar = this.temp.resolve("dependency").resolve("asset.jar");
|
||||
Files.createDirectories(assetJar.getParent());
|
||||
writeAssetJar(assetJar);
|
||||
writeApplicationJarWithAbsolutePath(this.temp.resolve("app.jar"), assetJar);
|
||||
String java = ProcessHandle.current().info().command().get();
|
||||
Process process = new ProcessBuilder(java, "-jar", "app.jar")
|
||||
.directory(this.temp.toFile())
|
||||
.start();
|
||||
assertThat(process.waitFor()).isZero();
|
||||
String result = StreamUtils.copyToString(process.getInputStream(), StandardCharsets.UTF_8);
|
||||
assertThat(result.replace("\\", "/")).contains("!!!!").contains("asset.jar!/assets/file.txt");
|
||||
}
|
||||
|
||||
private void writeAssetJar(Path path) throws Exception {
|
||||
try (JarOutputStream jar = new JarOutputStream(new FileOutputStream(path.toFile()))) {
|
||||
jar.putNextEntry(new ZipEntry("assets/"));
|
||||
@@ -392,6 +407,35 @@ class PathMatchingResourcePatternResolverTests {
|
||||
assertThat(new UrlResource(ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR).exists()).isTrue();
|
||||
}
|
||||
|
||||
private void writeApplicationJarWithAbsolutePath(Path path, Path assetJar) throws Exception {
|
||||
Manifest manifest = new Manifest();
|
||||
Attributes mainAttributes = manifest.getMainAttributes();
|
||||
mainAttributes.put(Name.CLASS_PATH, buildSpringClassPath() + assetJar.toAbsolutePath());
|
||||
mainAttributes.put(Name.MAIN_CLASS, ClassPathManifestEntriesTestApplication.class.getName());
|
||||
mainAttributes.put(Name.MANIFEST_VERSION, "1.0");
|
||||
try (JarOutputStream jar = new JarOutputStream(new FileOutputStream(path.toFile()), manifest)) {
|
||||
String appClassResource = ClassUtils.convertClassNameToResourcePath(
|
||||
ClassPathManifestEntriesTestApplication.class.getName()) + ClassUtils.CLASS_FILE_SUFFIX;
|
||||
String folder = "";
|
||||
for (String name : appClassResource.split("/")) {
|
||||
if (!name.endsWith(ClassUtils.CLASS_FILE_SUFFIX)) {
|
||||
folder += name + "/";
|
||||
jar.putNextEntry(new ZipEntry(folder));
|
||||
jar.closeEntry();
|
||||
}
|
||||
else {
|
||||
jar.putNextEntry(new ZipEntry(folder + name));
|
||||
try (InputStream in = getClass().getResourceAsStream(name)) {
|
||||
in.transferTo(jar);
|
||||
}
|
||||
jar.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
assertThat(new FileSystemResource(path).exists()).isTrue();
|
||||
assertThat(new UrlResource(ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR).exists()).isTrue();
|
||||
}
|
||||
|
||||
private String buildSpringClassPath() throws Exception {
|
||||
return copyClasses(PathMatchingResourcePatternResolver.class, "spring-core") +
|
||||
copyClasses(LogFactory.class, "commons-logging");
|
||||
|
||||
Reference in New Issue
Block a user