From 5e4b668e5aba4615ca4c291ad2020ae9d739ad37 Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Fri, 1 Oct 2021 15:31:17 -0400 Subject: [PATCH] 497 stable sorted CPE array (JSON and SPDX) (#522) * add small sorting change to our specificity Signed-off-by: Christopher Angelo Phillips --- cmd/packages.go | 2 +- .../common/cpe/sort_by_specificity.go | 12 ++++++++++-- .../common/cpe/sort_by_specificity_test.go | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/cmd/packages.go b/cmd/packages.go index fa60d363b..931640ba0 100644 --- a/cmd/packages.go +++ b/cmd/packages.go @@ -35,7 +35,7 @@ const ( Supports the following image sources: {{.appName}} {{.command}} yourrepo/yourimage:tag defaults to using images from a Docker daemon. If Docker is not present, the image is pulled directly from the registry. - {{.appName}} {{.command}} path/to/a/file/or/dir a Docker tar, OCI tar, OCI directory, or generic filesystem directory + {{.appName}} {{.command}} path/to/a/file/or/dir a Docker tar, OCI tar, OCI directory, or generic filesystem directory You can also explicitly specify the scheme to use: {{.appName}} {{.command}} docker:yourrepo/yourimage:tag explicitly use the Docker daemon diff --git a/syft/pkg/cataloger/common/cpe/sort_by_specificity.go b/syft/pkg/cataloger/common/cpe/sort_by_specificity.go index bcb3cd3b5..03b1a741e 100644 --- a/syft/pkg/cataloger/common/cpe/sort_by_specificity.go +++ b/syft/pkg/cataloger/common/cpe/sort_by_specificity.go @@ -18,10 +18,18 @@ func (c BySpecificity) Less(i, j int) bool { iScore := weightedCountForSpecifiedFields(c[i]) jScore := weightedCountForSpecifiedFields(c[j]) - if iScore == jScore { + // check weighted sort first + if iScore != jScore { + return iScore > jScore + } + + // sort longer fields to top + if countFieldLength(c[i]) != countFieldLength(c[j]) { return countFieldLength(c[i]) > countFieldLength(c[j]) } - return iScore > jScore + + // if score and length are equal then text sort + return c[i].BindToFmtString() < c[j].BindToFmtString() } func countFieldLength(cpe wfn.Attributes) int { diff --git a/syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go b/syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go index 4d0d300bb..f979bd8fb 100644 --- a/syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go +++ b/syft/pkg/cataloger/common/cpe/sort_by_specificity_test.go @@ -80,6 +80,25 @@ func TestCPESpecificity(t *testing.T) { mustCPE("cpe:2.3:a:1:*:333:*:*:*:*:*:*:*"), }, }, + { + name: "sort by mix of field length, specificity, dash", + input: []pkg.CPE{ + mustCPE("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + }, + expected: []pkg.CPE{ + mustCPE("cpe:2.3:a:alpine-keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine-keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine_keys:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine_keys:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine:alpine-keys:2.3-r1:*:*:*:*:*:*:*"), + mustCPE("cpe:2.3:a:alpine:alpine_keys:2.3-r1:*:*:*:*:*:*:*"), + }, + }, } for _, test := range tests {