diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 8abecc5df36..955f8cfd9e3 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 4123d1dde96..b73e4051150 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 00000000000..37f39009ce9 --- /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 00000000000..9952a80dc68 --- /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 00000000000..372fefd3fce --- /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 + +