diff --git a/go.mod b/go.mod index f44161f..bba73a3 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.21 require ( github.com/ezamriy/gorpm v0.0.0-20160905202458-25f7273cbf51 + github.com/google/go-cmp v0.6.0 github.com/hashicorp/go-version v1.7.0 github.com/mattn/go-sqlite3 v1.14.22 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 74e90ea..2265ef3 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= diff --git a/vmaas/vulnerabilities.go b/vmaas/vulnerabilities.go index 083a254..c9a8f60 100644 --- a/vmaas/vulnerabilities.go +++ b/vmaas/vulnerabilities.go @@ -6,6 +6,7 @@ import ( "sort" "time" + "github.com/google/go-cmp/cmp" "github.com/hashicorp/go-version" "github.com/pkg/errors" "github.com/redhatinsights/vmaas-lib/vmaas/utils" @@ -186,7 +187,14 @@ func evaluate(c *Cache, opts *options, request *Request) (*VulnerabilitiesCvesDe func evaluateUnpatchedCves(c *Cache, products []ProductsPackage, cves *VulnerabilitiesCvesDetails) { for _, pp := range products { + seenProducts := make(map[CSAFProduct]bool, len(pp.ProductsUnfixed)) for _, product := range pp.ProductsUnfixed { + if seenProducts[product] { + // duplicate product in pp.ProductsUnfixed + // skip processing of already processed product + continue + } + seenProducts[product] = true module := product.ModuleStream cn := CpeIDNameID{CpeID: product.CpeID, NameID: product.PackageNameID} csafCves := c.CSAFCVEs[cn][product] @@ -210,7 +218,14 @@ func evaluateUnpatchedCves(c *Cache, products []ProductsPackage, cves *Vulnerabi func evaluateManualCves(c *Cache, products []ProductsPackage, cves *VulnerabilitiesCvesDetails) { for _, pp := range products { pp := pp // make copy because &pp is used + seenProducts := make(map[CSAFProduct]bool, len(pp.ProductsFixed)) for _, product := range pp.ProductsFixed { + if seenProducts[product] { + // duplicate product in pp.ProductsFixed + // skip processing of already processed product + continue + } + seenProducts[product] = true updateNevra := pkgID2Nevra(c, product.PackageID) if !isApplicable(c, &updateNevra, &pp.Package.Nevra) { continue @@ -766,7 +781,21 @@ func updateCves(cves map[string]VulnerabilityDetail, cve string, pkg Package, er affectedPackage.ModuleStreamPtrs.Module = &module.Module affectedPackage.ModuleStreamPtrs.Stream = &module.Stream } - vulnDetail.Affected = append(vulnDetail.Affected, affectedPackage) + vulnDetail.Affected = appendUniq(vulnDetail.Affected, &affectedPackage) } cves[cve] = vulnDetail } + +func appendUniq(affected []AffectedPackage, item *AffectedPackage) []AffectedPackage { + if item == nil { + return affected + } + + for _, a := range affected { + if cmp.Equal(a, *item) { + return affected + } + } + affected = append(affected, *item) + return affected +}