mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
fix: duplicate entries in cyclonedx dependency list (#2063)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
This commit is contained in:
parent
d08e2be768
commit
4ae94c37eb
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/CycloneDX/cyclonedx-go"
|
"github.com/CycloneDX/cyclonedx-go"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal"
|
"github.com/anchore/syft/internal"
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
@ -139,7 +140,7 @@ func isExpressiblePackageRelationship(ty artifact.RelationshipType) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func toDependencies(relationships []artifact.Relationship) []cyclonedx.Dependency {
|
func toDependencies(relationships []artifact.Relationship) []cyclonedx.Dependency {
|
||||||
result := make([]cyclonedx.Dependency, 0)
|
dependencies := map[string]*cyclonedx.Dependency{}
|
||||||
for _, r := range relationships {
|
for _, r := range relationships {
|
||||||
exists := isExpressiblePackageRelationship(r.Type)
|
exists := isExpressiblePackageRelationship(r.Type)
|
||||||
if !exists {
|
if !exists {
|
||||||
@ -160,15 +161,32 @@ func toDependencies(relationships []artifact.Relationship) []cyclonedx.Dependenc
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// ind dep
|
toRef := deriveBomRef(toPkg)
|
||||||
|
dep := dependencies[toRef]
|
||||||
innerDeps := []string{}
|
if dep == nil {
|
||||||
innerDeps = append(innerDeps, deriveBomRef(fromPkg))
|
dep = &cyclonedx.Dependency{
|
||||||
result = append(result, cyclonedx.Dependency{
|
Ref: toRef,
|
||||||
Ref: deriveBomRef(toPkg),
|
Dependencies: &[]string{},
|
||||||
Dependencies: &innerDeps,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
dependencies[toRef] = dep
|
||||||
|
}
|
||||||
|
|
||||||
|
fromRef := deriveBomRef(fromPkg)
|
||||||
|
if !slices.Contains(*dep.Dependencies, fromRef) {
|
||||||
|
*dep.Dependencies = append(*dep.Dependencies, fromRef)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]cyclonedx.Dependency, 0, len(dependencies))
|
||||||
|
for _, dep := range dependencies {
|
||||||
|
slices.Sort(*dep.Dependencies)
|
||||||
|
result = append(result, *dep)
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.SortFunc(result, func(a, b cyclonedx.Dependency) bool {
|
||||||
|
return a.Ref < b.Ref
|
||||||
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package cyclonedxhelpers
|
package cyclonedxhelpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/CycloneDX/cyclonedx-go"
|
"github.com/CycloneDX/cyclonedx-go"
|
||||||
@ -43,28 +44,34 @@ func Test_relationships(t *testing.T) {
|
|||||||
p1 := pkg.Package{
|
p1 := pkg.Package{
|
||||||
Name: "p1",
|
Name: "p1",
|
||||||
}
|
}
|
||||||
p1.SetID()
|
|
||||||
|
|
||||||
p2 := pkg.Package{
|
p2 := pkg.Package{
|
||||||
Name: "p2",
|
Name: "p2",
|
||||||
}
|
}
|
||||||
p2.SetID()
|
|
||||||
|
|
||||||
p3 := pkg.Package{
|
p3 := pkg.Package{
|
||||||
Name: "p3",
|
Name: "p3",
|
||||||
}
|
}
|
||||||
p3.SetID()
|
|
||||||
|
p4 := pkg.Package{
|
||||||
|
Name: "p4",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range []*pkg.Package{&p1, &p2, &p3, &p4} {
|
||||||
|
p.PURL = fmt.Sprintf("pkg:generic/%s@%s", p.Name, p.Name)
|
||||||
|
p.SetID()
|
||||||
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
sbom sbom.SBOM
|
sbom sbom.SBOM
|
||||||
expected []string
|
expected *[]cyclonedx.Dependency
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "package dependencyOf relationships output as dependencies",
|
name: "package dependencyOf relationships output as dependencies",
|
||||||
sbom: sbom.SBOM{
|
sbom: sbom.SBOM{
|
||||||
Artifacts: sbom.Artifacts{
|
Artifacts: sbom.Artifacts{
|
||||||
Packages: pkg.NewCollection(p1, p2, p3),
|
Packages: pkg.NewCollection(p1, p2, p3, p4),
|
||||||
},
|
},
|
||||||
Relationships: []artifact.Relationship{
|
Relationships: []artifact.Relationship{
|
||||||
{
|
{
|
||||||
@ -77,9 +84,28 @@ func Test_relationships(t *testing.T) {
|
|||||||
To: p1,
|
To: p1,
|
||||||
Type: artifact.DependencyOfRelationship,
|
Type: artifact.DependencyOfRelationship,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
From: p4,
|
||||||
|
To: p2,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: &[]cyclonedx.Dependency{
|
||||||
|
{
|
||||||
|
Ref: deriveBomRef(p1),
|
||||||
|
Dependencies: &[]string{
|
||||||
|
deriveBomRef(p2),
|
||||||
|
deriveBomRef(p3),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Ref: deriveBomRef(p2),
|
||||||
|
Dependencies: &[]string{
|
||||||
|
deriveBomRef(p4),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expected: []string{p2.Name, p3.Name},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "package contains relationships not output",
|
name: "package contains relationships not output",
|
||||||
@ -108,28 +134,7 @@ func Test_relationships(t *testing.T) {
|
|||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
cdx := ToFormatModel(test.sbom)
|
cdx := ToFormatModel(test.sbom)
|
||||||
got := cdx.Dependencies
|
got := cdx.Dependencies
|
||||||
|
require.Equal(t, test.expected, got)
|
||||||
var deps []string
|
|
||||||
if got != nil {
|
|
||||||
for _, r := range *got {
|
|
||||||
for _, d := range *r.Dependencies {
|
|
||||||
c := findComponent(cdx, d)
|
|
||||||
require.NotNil(t, c)
|
|
||||||
deps = append(deps, c.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
require.Equal(t, test.expected, deps)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func findComponent(cdx *cyclonedx.BOM, bomRef string) *cyclonedx.Component {
|
|
||||||
for _, c := range *cdx.Components {
|
|
||||||
if c.BOMRef == bomRef {
|
|
||||||
return &c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user