diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go
index 8abecc5df36c..955f8cfd9e33 100644
--- a/pkg/dependency/parser/java/pom/parse.go
+++ b/pkg/dependency/parser/java/pom/parse.go
@@ -105,10 +105,10 @@ func (p *parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
// Cache root POM
p.cache.put(result.artifact, result)
- return p.parseRoot(root.artifact())
+ return p.parseRoot(root.artifact(), make(map[string]struct{}))
}
-func (p *parser) parseRoot(root artifact) ([]types.Library, []types.Dependency, error) {
+func (p *parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]types.Library, []types.Dependency, error) {
// Prepare a queue for dependencies
queue := newArtifactQueue()
@@ -132,7 +132,12 @@ func (p *parser) parseRoot(root artifact) ([]types.Library, []types.Dependency,
// Modules should be handled separately so that they can have independent dependencies.
// It means multi-module allows for duplicate dependencies.
if art.Module {
- moduleLibs, moduleDeps, err := p.parseRoot(art)
+ if _, ok := uniqModules[art.String()]; ok {
+ continue
+ }
+ uniqModules[art.String()] = struct{}{}
+
+ moduleLibs, moduleDeps, err := p.parseRoot(art, uniqModules)
if err != nil {
return nil, nil, err
}
diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go
index 4123d1dde960..b73e40511507 100644
--- a/pkg/dependency/parser/java/pom/parse_test.go
+++ b/pkg/dependency/parser/java/pom/parse_test.go
@@ -959,6 +959,43 @@ func TestPom_Parse(t *testing.T) {
},
},
},
+ {
+ name: "Infinity loop for modules",
+ inputFile: filepath.Join("testdata", "modules-infinity-loop", "pom.xml"),
+ local: true,
+ want: []types.Library{
+ // as module
+ {
+ ID: "org.example:module-1:2.0.0",
+ Name: "org.example:module-1",
+ Version: "2.0.0",
+ },
+ // as dependency
+ {
+ ID: "org.example:module-1:2.0.0",
+ Name: "org.example:module-1",
+ Version: "2.0.0",
+ },
+ {
+ ID: "org.example:module-2:3.0.0",
+ Name: "org.example:module-2",
+ Version: "3.0.0",
+ },
+ {
+ ID: "org.example:root:1.0.0",
+ Name: "org.example:root",
+ Version: "1.0.0",
+ },
+ },
+ wantDeps: []types.Dependency{
+ {
+ ID: "org.example:module-2:3.0.0",
+ DependsOn: []string{
+ "org.example:module-1:2.0.0",
+ },
+ },
+ },
+ },
{
name: "multi module soft requirement",
inputFile: filepath.Join("testdata", "multi-module-soft-requirement", "pom.xml"),
diff --git a/pkg/dependency/parser/java/pom/testdata/modules-infinity-loop/module-1/module-2/pom.xml b/pkg/dependency/parser/java/pom/testdata/modules-infinity-loop/module-1/module-2/pom.xml
new file mode 100644
index 000000000000..37f39009ce97
--- /dev/null
+++ b/pkg/dependency/parser/java/pom/testdata/modules-infinity-loop/module-1/module-2/pom.xml
@@ -0,0 +1,16 @@
+
+ 4.0.0
+
+ module-2
+ org.example
+ 3.0.0
+
+
+
+ org.example
+ module-1
+ 2.0.0
+
+
+
diff --git a/pkg/dependency/parser/java/pom/testdata/modules-infinity-loop/module-1/pom.xml b/pkg/dependency/parser/java/pom/testdata/modules-infinity-loop/module-1/pom.xml
new file mode 100644
index 000000000000..9952a80dc685
--- /dev/null
+++ b/pkg/dependency/parser/java/pom/testdata/modules-infinity-loop/module-1/pom.xml
@@ -0,0 +1,12 @@
+
+ 4.0.0
+
+ module-1
+ org.example
+ 2.0.0
+
+
+ module-2
+
+
diff --git a/pkg/dependency/parser/java/pom/testdata/modules-infinity-loop/pom.xml b/pkg/dependency/parser/java/pom/testdata/modules-infinity-loop/pom.xml
new file mode 100644
index 000000000000..372fefd3fce9
--- /dev/null
+++ b/pkg/dependency/parser/java/pom/testdata/modules-infinity-loop/pom.xml
@@ -0,0 +1,13 @@
+
+ 4.0.0
+
+ root
+ org.example
+ 1.0.0
+
+
+ module-1
+ module-2
+
+