You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by mi...@apache.org on 2020/12/13 14:11:24 UTC

[maven] branch master updated: [MNG-7034] StackOverflowError thrown if a cycle exists in BOM imports

This is an automated email from the ASF dual-hosted git repository.

michaelo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/master by this push:
     new be8ced6  [MNG-7034] StackOverflowError thrown if a cycle exists in BOM imports
be8ced6 is described below

commit be8ced6be3e9758a2373a8b62647329a2110151f
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Nov 25 20:12:04 2020 +0100

    [MNG-7034] StackOverflowError thrown if a cycle exists in BOM imports
    
    This closes #399
---
 .../maven/model/building/DefaultModelBuilder.java  |  12 +-
 .../model/building/DefaultModelBuilderTest.java    | 147 +++++++++++++++++++++
 2 files changed, 156 insertions(+), 3 deletions(-)

diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
index 51c68fb..8b31908 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
@@ -256,11 +256,17 @@ public class DefaultModelBuilder
         return this;
     }
     
-    @SuppressWarnings( "checkstyle:methodlength" )
     @Override
     public ModelBuildingResult build( ModelBuildingRequest request )
         throws ModelBuildingException
     {
+        return build( request, new LinkedHashSet<>() );
+    }
+
+    @SuppressWarnings( "checkstyle:methodlength" )
+    protected ModelBuildingResult build( ModelBuildingRequest request, Collection<String> importIds )
+        throws ModelBuildingException
+    {
         // phase 1
         DefaultModelBuildingResult result = new DefaultModelBuildingResult();
 
@@ -449,7 +455,7 @@ public class DefaultModelBuilder
 
         if ( !request.isTwoPhaseBuilding() )
         {
-            build( request, result );
+            build( request, result, importIds );
         }
 
         return result;
@@ -1427,7 +1433,7 @@ public class DefaultModelBuilder
                     final ModelBuildingResult importResult;
                     try
                     {
-                        importResult = build( importRequest );
+                        importResult = build( importRequest, importIds );
                     }
                     catch ( ModelBuildingException e )
                     {
diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java
new file mode 100644
index 0000000..2b6d53a
--- /dev/null
+++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java
@@ -0,0 +1,147 @@
+package org.apache.maven.model.building;
+
+  /*
+ * 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.
+ */
+
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Parent;
+import org.apache.maven.model.Repository;
+import org.apache.maven.model.resolution.InvalidRepositoryException;
+import org.apache.maven.model.resolution.ModelResolver;
+import org.apache.maven.model.resolution.UnresolvableModelException;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+
+/**
+ * @author Guillaume Nodet
+ */
+public class DefaultModelBuilderTest
+{
+
+    private static final String BASE1_ID = "thegroup:base1:pom";
+
+    private static final String BASE1 = "<project>\n" +
+            "  <modelVersion>4.0.0</modelVersion>\n" +
+            "  <groupId>thegroup</groupId>\n" +
+            "  <artifactId>base1</artifactId>\n" +
+            "  <version>1</version>\n" +
+            "  <packaging>pom</packaging>\n" +
+            "  <dependencyManagement>\n" +
+            "    <dependencies>\n" +
+            "      <dependency>\n" +
+            "        <groupId>thegroup</groupId>\n" +
+            "        <artifactId>base2</artifactId>\n" +
+            "        <version>1</version>\n" +
+            "        <type>pom</type>\n" +
+            "        <scope>import</scope>\n" +
+            "      </dependency>\n" +
+            "    </dependencies>\n" +
+            "  </dependencyManagement>\n" +
+            "</project>\n";
+
+    private static final String BASE2_ID = "thegroup:base2:pom";
+
+    private static final String BASE2 = "<project>\n" +
+            "  <modelVersion>4.0.0</modelVersion>\n" +
+            "  <groupId>thegroup</groupId>\n" +
+            "  <artifactId>base2</artifactId>\n" +
+            "  <version>1</version>\n" +
+            "  <packaging>pom</packaging>\n" +
+            "  <dependencyManagement>\n" +
+            "    <dependencies>\n" +
+            "      <dependency>\n" +
+            "        <groupId>thegroup</groupId>\n" +
+            "        <artifactId>base1</artifactId>\n" +
+            "        <version>1</version>\n" +
+            "        <type>pom</type>\n" +
+            "        <scope>import</scope>\n" +
+            "      </dependency>\n" +
+            "    </dependencies>\n" +
+            "  </dependencyManagement>\n" +
+            "</project>\n";
+
+    @Test
+    public void testCycleInImports()
+            throws Exception
+    {
+        ModelBuilder builder = new DefaultModelBuilderFactory().newInstance();
+        assertNotNull( builder );
+
+        DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
+        request.setModelSource( new StringModelSource( BASE1 ) );
+        request.setModelResolver( new CycleInImportsResolver() );
+
+        assertThrows( ModelBuildingException.class, () -> builder.build( request ) );
+    }
+
+    static class CycleInImportsResolver extends BaseModelResolver
+    {
+        @Override
+        public ModelSource resolveModel(Dependency dependency) throws UnresolvableModelException
+        {
+            switch ( dependency.getManagementKey() )
+            {
+                case BASE1_ID: return new StringModelSource( BASE1 );
+                case BASE2_ID: return new StringModelSource( BASE2 );
+            }
+            return null;
+        }
+    }
+
+    static class BaseModelResolver implements ModelResolver
+    {
+        @Override
+        public ModelSource resolveModel( String groupId, String artifactId, String version )
+                throws UnresolvableModelException
+        {
+            return null;
+        }
+
+        @Override
+        public ModelSource resolveModel( Parent parent ) throws UnresolvableModelException
+        {
+            return null;
+        }
+
+        @Override
+        public ModelSource resolveModel( Dependency dependency ) throws UnresolvableModelException
+        {
+            return null;
+        }
+
+        @Override
+        public void addRepository( Repository repository ) throws InvalidRepositoryException
+        {
+        }
+
+        @Override
+        public void addRepository(Repository repository, boolean replace) throws InvalidRepositoryException
+        {
+        }
+
+        @Override
+        public ModelResolver newCopy()
+        {
+            return this;
+        }
+    }
+
+}