fix:after compliance applied,the relationship concerning the original one should be omitted (#4419)

---------
Signed-off-by: Yuntao Hu <victorhu493@gmail.com>
This commit is contained in:
VictorHuu 2025-12-05 04:30:16 +08:00 committed by GitHub
parent 155738aba7
commit baca32f04a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 109 additions and 1 deletions

View File

@ -79,6 +79,10 @@ func (i *Index) Remove(id artifact.ID) {
func (i *Index) Replace(ogID artifact.ID, replacement artifact.Identifiable) {
for _, mapped := range fromMappedByID(i.fromID, ogID) {
// the stale relationship(i.e. if there's an elder ID in either side) should be discarded
if len(fromMappedByID(i.toID, mapped.relationship.To.ID())) == 0 {
continue
}
i.Add(artifact.Relationship{
From: replacement,
To: mapped.relationship.To,
@ -87,6 +91,10 @@ func (i *Index) Replace(ogID artifact.ID, replacement artifact.Identifiable) {
}
for _, mapped := range fromMappedByID(i.toID, ogID) {
// same as the above
if len(fromMappedByID(i.fromID, mapped.relationship.To.ID())) == 0 {
continue
}
i.Add(artifact.Relationship{
From: mapped.relationship.From,
To: replacement,

View File

@ -98,6 +98,24 @@ func createModuleRelationships(main pkg.Package, deps []pkg.Package) []artifact.
return relationships
}
// moduleEqual is used to deduplicate go modules especially the sub module may be identical to the main one
func moduleEqual(lhs, rhs *debug.Module) bool {
if lhs == rhs {
return true
}
if lhs == nil || rhs == nil {
return false
}
if lhs.Path != rhs.Path ||
lhs.Version != rhs.Version ||
lhs.Sum != rhs.Sum {
return false
}
return moduleEqual(lhs.Replace, rhs.Replace)
}
var emptyModule debug.Module
var moduleFromPartialPackageBuild = debug.Module{Path: "command-line-arguments"}
@ -115,7 +133,9 @@ func (c *goBinaryCataloger) buildGoPkgInfo(ctx context.Context, resolver file.Re
if dep == nil {
continue
}
if moduleEqual(dep, &mod.Main) {
continue
}
lics := c.licenseResolver.getLicenses(ctx, resolver, dep.Path, dep.Version)
gover, experiments := getExperimentsFromVersion(mod.GoVersion)

View File

@ -847,6 +847,86 @@ func TestBuildGoPkgInfo(t *testing.T) {
unmodifiedMain,
},
},
{
name: "parse a populated mod string and returns packages when a replace directive and synthetic main module 'command line arguments' exists",
mod: &extendedBuildInfo{
BuildInfo: &debug.BuildInfo{
GoVersion: goCompiledVersion,
Main: debug.Module{Path: "command-line-arguments", Version: devel},
Settings: []debug.BuildSetting{
{Key: "GOARCH", Value: archDetails},
{Key: "GOOS", Value: "linux"},
{Key: "GOAMD64", Value: "v1"},
},
Path: "command-line-arguments",
Deps: []*debug.Module{
{
Path: "example.com/mylib",
Version: "v0.0.0",
Replace: &debug.Module{
Path: "./mylib",
Version: devel,
},
},
{
Path: "command-line-arguments",
Version: devel,
},
},
},
cryptoSettings: nil,
arch: archDetails,
},
expected: []pkg.Package{
{
Name: "example.com/mylib",
Version: "",
PURL: "pkg:golang/example.com/mylib",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Locations: file.NewLocationSet(
file.NewLocationFromCoordinates(
file.Coordinates{
RealPath: "/a-path",
FileSystemID: "layer-id",
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
H1Digest: "",
MainModule: "command-line-arguments",
},
},
{
Name: "command-line-arguments",
Version: "",
PURL: "pkg:golang/command-line-arguments",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Locations: file.NewLocationSet(
file.NewLocationFromCoordinates(
file.Coordinates{
RealPath: "/a-path",
FileSystemID: "layer-id",
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Metadata: pkg.GolangBinaryBuildinfoEntry{
BuildSettings: pkg.KeyValues{
{Key: "GOARCH", Value: "amd64"},
{Key: "GOOS", Value: "linux"},
{Key: "GOAMD64", Value: "v1"},
},
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
H1Digest: "",
MainModule: "command-line-arguments",
},
},
},
},
{
name: "parse main mod and replace devel with pattern from binary contents",
cfg: func() *CatalogerConfig {