Sort generated CPEs by specificity (#289)

Signed-off-by: Dan Luhring <dan.luhring@anchore.com>
This commit is contained in:
Dan Luhring 2020-12-11 12:08:39 -05:00 committed by GitHub
parent 52bac6e2fd
commit 737a81c38c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 8 deletions

View File

@ -2,6 +2,7 @@ package cataloger
import (
"fmt"
"sort"
"strings"
"github.com/anchore/syft/internal"
@ -12,6 +13,17 @@ import (
// this is functionally equivalent to "*" and consistent with no input given (thus easier to test)
const any = ""
func newCPE(product, vendor, version, targetSW string) wfn.Attributes {
cpe := *(wfn.NewAttributesWithAny())
cpe.Part = "a"
cpe.Product = product
cpe.Vendor = vendor
cpe.Version = version
cpe.TargetSW = targetSW
return cpe
}
// generatePackageCPEs Create a list of CPEs, trying to guess the vendor, product tuple and setting TargetSoftware if possible
func generatePackageCPEs(p pkg.Package) []pkg.CPE {
targetSws := candidateTargetSoftwareAttrs(p)
@ -31,18 +43,14 @@ func generatePackageCPEs(p pkg.Package) []pkg.CPE {
keys.Add(key)
// add a new entry...
candidateCpe := wfn.NewAttributesWithAny()
candidateCpe.Part = "a"
candidateCpe.Product = product
candidateCpe.Vendor = vendor
candidateCpe.Version = p.Version
candidateCpe.TargetSW = targetSw
cpes = append(cpes, *candidateCpe)
c := newCPE(product, vendor, p.Version, targetSw)
cpes = append(cpes, c)
}
}
}
sort.Sort(ByCPESpecificity(cpes))
return cpes
}

View File

@ -0,0 +1,31 @@
package cataloger
import "github.com/facebookincubator/nvdtools/wfn"
type ByCPESpecificity []wfn.Attributes
// Implementing sort.Interface
func (c ByCPESpecificity) Len() int { return len(c) }
func (c ByCPESpecificity) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c ByCPESpecificity) Less(i, j int) bool {
return countSpecifiedFields(c[i]) > countSpecifiedFields(c[j])
}
func countSpecifiedFields(cpe wfn.Attributes) int {
checksForSpecifiedField := []func(cpe wfn.Attributes) bool{
func(cpe wfn.Attributes) bool { return cpe.Part != "" },
func(cpe wfn.Attributes) bool { return cpe.Product != "" },
func(cpe wfn.Attributes) bool { return cpe.Vendor != "" },
func(cpe wfn.Attributes) bool { return cpe.Version != "" },
func(cpe wfn.Attributes) bool { return cpe.TargetSW != "" },
}
count := 0
for _, fieldIsSpecified := range checksForSpecifiedField {
if fieldIsSpecified(cpe) {
count++
}
}
return count
}