You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/10/22 10:12:14 UTC
(maven) branch maven-4.0.x updated: Resolve multiModuleProjectDirectory lexically instead of canonically (fix #11167) (#13650) (#13673)
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch maven-4.0.x
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/maven-4.0.x by this push:
new 29a5346f9e Resolve multiModuleProjectDirectory lexically instead of canonically (fix #11167) (#13650) (#13673)
29a5346f9e is described below
commit 29a5346f9ecd3e2c91e6fb8b6ebac78509efb71c
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu Oct 22 12:12:08 2026 +0200
Resolve multiModuleProjectDirectory lexically instead of canonically (fix #11167) (#13650) (#13673)
getCanonicalFile() asks the OS to resolve the path, which can follow a
symlink, a junction, or (since JDK-8355342, on JDK 25+) a mapped
Windows network drive to a different location, corrupting the reactor
root that every module/parent path is resolved against.
Routed through the same getCanonicalPath(Path) helper this class
already uses elsewhere since #11250, which only normalizes the path
lexically.
Co-authored-by: Arturo Bernal <ab...@apache.org>
---
.../main/java/org/apache/maven/cli/MavenCli.java | 11 +++++-----
.../java/org/apache/maven/cli/MavenCliTest.java | 25 ++++++++++++++++++++++
2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
index c0f8f10ce9..e9f2cfc03b 100644
--- a/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
+++ b/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
@@ -346,11 +346,12 @@ void initialize(CliRequest cliRequest) throws ExitException {
throw new ExitException(1);
}
File basedir = new File(basedirProperty);
- try {
- cliRequest.multiModuleProjectDirectory = basedir.getCanonicalFile();
- } catch (IOException e) {
- cliRequest.multiModuleProjectDirectory = basedir.getAbsoluteFile();
- }
+ // Resolve lexically rather than through getCanonicalFile(), which asks the OS to resolve the path
+ // and can substitute it with a different one when a segment is a symlink, junction, or (on Windows)
+ // a mapped network drive, corrupting the reactor root that every relative module/parent path is
+ // later resolved against (MNG-11167).
+ cliRequest.multiModuleProjectDirectory =
+ getCanonicalPath(basedir.toPath()).toFile();
}
// We need to locate the top level project which may be pointed at using
diff --git a/compat/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java b/compat/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
index 5867a4537c..44c8ce6212 100644
--- a/compat/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
+++ b/compat/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
@@ -20,6 +20,7 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
@@ -60,6 +61,7 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -211,6 +213,29 @@ void testMavenConfigInvalid() throws Exception {
assertThrows(ParseException.class, () -> cli.cli(request));
}
+ /**
+ * MNG-11167: {@code multiModuleProjectDirectory} must keep the path as given, not the path that
+ * {@link File#getCanonicalFile()} resolves a symlinked (or, on Windows, a mapped network drive)
+ * segment to, or every module/parent path resolved relative to it inherits the wrong base.
+ */
+ @Test
+ void testMultiModuleProjectDirectoryIsNotResolvedThroughASymlink(@TempDir Path tempDir) throws Exception {
+ Path real = Files.createDirectories(tempDir.resolve("real"));
+ Path link = tempDir.resolve("link");
+ try {
+ Files.createSymbolicLink(link, real);
+ } catch (IOException | UnsupportedOperationException e) {
+ assumeTrue(false, "symbolic links are not supported on this machine");
+ }
+
+ System.setProperty(MavenCli.MULTIMODULE_PROJECT_DIRECTORY, link.toString());
+ CliRequest request = new CliRequest(new String[0], null);
+
+ cli.initialize(request);
+
+ assertEquals(link.toString(), request.multiModuleProjectDirectory.getPath());
+ }
+
/**
* Read .mvn/maven.config with the following definitions:
* <pre>