Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -678,8 +678,14 @@ private Map<String, String> getEnhancedProperties(Model model, Path rootDirector
if (!Objects.equals(rootDirectory, model.getProjectDirectory())) {
Path rootModelPath = modelProcessor.locateExistingPom(rootDirectory);
if (rootModelPath != null) {
Model rootModel = derive(Sources.buildSource(rootModelPath)).readFileModel();
properties.putAll(getPropertiesWithProfiles(rootModel, properties));
// Check if the root model path is within the root directory to prevent infinite loops
// This can happen when a .mvn directory exists in a subdirectory and parent inference
// tries to read models above the discovered root directory
if (isParentWithinRootDirectory(rootModelPath, rootDirectory)) {
Model rootModel =
derive(Sources.buildSource(rootModelPath)).readFileModel();
properties.putAll(getPropertiesWithProfiles(rootModel, properties));
}
}
} else {
properties.putAll(getPropertiesWithProfiles(model, properties));
Expand Down Expand Up @@ -1561,6 +1567,18 @@ Model doReadFileModel() throws ModelBuilderException {
pomPath = modelProcessor.locateExistingPom(pomPath);
}
if (pomPath != null && Files.isRegularFile(pomPath)) {
// Check if parent POM is above the root directory
if (!isParentWithinRootDirectory(pomPath, rootDirectory)) {
add(
Severity.FATAL,
Version.BASE,
"Parent POM " + pomPath + " is located above the root directory "
+ rootDirectory
+ ". This setup is invalid when a .mvn directory exists in a subdirectory.",
parent.getLocation("relativePath"));
throw newModelBuilderException();
}

Model parentModel =
derive(Sources.buildSource(pomPath)).readFileModel();
String parentGroupId = getGroupId(parentModel);
Expand Down Expand Up @@ -2588,4 +2606,29 @@ private static <T, A> List<T> map(List<T> resources, BiFunction<T, A, T> mapper,
}
return newResources;
}

/**
* Checks if the parent POM path is within the root directory.
* This prevents invalid setups where a parent POM is located above the root directory.
*
* @param parentPath the path to the parent POM
* @param rootDirectory the root directory
* @return true if the parent is within the root directory, false otherwise
*/
private static boolean isParentWithinRootDirectory(Path parentPath, Path rootDirectory) {
if (parentPath == null || rootDirectory == null) {
return true; // Allow if either is null (fallback behavior)
}

try {
Path normalizedParent = parentPath.toAbsolutePath().normalize();
Path normalizedRoot = rootDirectory.toAbsolutePath().normalize();

// Check if the parent path starts with the root directory path
return normalizedParent.startsWith(normalizedRoot);
} catch (Exception e) {
// If there's any issue with path resolution, allow it (fallback behavior)
return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.it;

import java.io.File;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertThrows;

/**
* This is a test set for <a href="https://github.com/apache/maven/issues/11321">GH-11321</a>.
* Verify that Maven properly rejects setups where a parent POM is located above the root directory
* when a .mvn directory exists in a subdirectory and Maven is invoked with -f pointing to that subdirectory.
*
* @since 4.0.0
*/
public class MavenITgh11321Test extends AbstractMavenIntegrationTestCase {

/**
* Verify that Maven properly rejects setups where a parent POM is located above the root directory.
* When Maven is invoked with -f deps/ where deps contains a .mvn directory, and the deps/pom.xml
* uses parent inference to find a parent above the root directory, it should fail with a proper error message.
*
* @throws Exception in case of failure
*/
@Test
public void testParentAboveRootDirectoryRejected() throws Exception {
File testDir = extractResources("/gh-11321-parent-above-root");

// First, verify that normal build works from the actual root
Verifier verifier = newVerifier(testDir.getAbsolutePath());
verifier.addCliArgument("validate");
verifier.execute();
verifier.verifyErrorFreeLog();

// Now test with -f pointing to the subdirectory that contains .mvn
// This should fail with a proper error message about parent being above root
verifier = newVerifier(testDir.getAbsolutePath());
verifier.addCliArgument("-f");
verifier.addCliArgument("deps");
verifier.addCliArgument("validate");
assertThrows(
VerificationException.class,
verifier::execute,
"Expected validation to fail when using invalid project structure");
verifier.verifyTextInLog("Parent POM");
verifier.verifyTextInLog("is located above the root directory");
verifier.verifyTextInLog("This setup is invalid when a .mvn directory exists in a subdirectory");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 https://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
<!-- Empty extensions file to make .mvn directory a valid root marker -->
</extensions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.1.0">
<parent />
<artifactId>deps</artifactId>
<packaging>pom</packaging>

<name>Maven Integration Test :: gh-11321 :: Deps Module</name>
<description>Module with .mvn directory that uses parent inference</description>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.1.0" root="true">
<groupId>org.apache.maven.its.gh11321</groupId>
<artifactId>parent-above-root</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Maven Integration Test :: gh-11321 :: Parent Above Root</name>
<description>Test that Maven rejects setups where parent POM is above root directory</description>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>