diff --git a/grype/db/v5/search/cpe.go b/grype/db/v5/search/cpe.go index ecad3e05cc5..f69c055a160 100644 --- a/grype/db/v5/search/cpe.go +++ b/grype/db/v5/search/cpe.go @@ -177,7 +177,33 @@ func addNewMatch(matchesByFingerprint map[match.Fingerprint]match.Match, vuln vu candidateMatch = existingMatch } - sortFixedVersions(candidateMatch, p) + // filter unrelated fixed versions in case fixed versions are larger than 1 + if len(candidateMatch.Vulnerability.Fix.Versions) > 1 { + var filteredVersions []string + format := version.FormatFromPkg(p) + cons, err := version.GetConstraint(fmt.Sprintf("<=%s", candidateMatch.Package.Version), format) + if err != nil { + log.WithFields("package", p.Name).Trace("skipping filtering fixed versions") + } + + for _, v := range candidateMatch.Vulnerability.Fix.Versions { + comparedVersion, err := version.NewVersion(v, format) + if err != nil { + log.WithFields("package", p.Name, "version", v).Trace("error while creating version in filtering fixed versions") + } + skip, err := cons.Satisfied(comparedVersion) + if err != nil { + log.WithFields("package", p.Name, "version", v).Trace("error while comparing version in filtering fixed versions") + continue + } + if skip { + continue + } + filteredVersions = append(filteredVersions, v) + } + + candidateMatch.Vulnerability.Fix.Versions = filteredVersions + } candidateMatch.Details = addMatchDetails(candidateMatch.Details, match.Detail{ @@ -205,56 +231,6 @@ func addNewMatch(matchesByFingerprint map[match.Fingerprint]match.Match, vuln vu matchesByFingerprint[candidateMatch.Fingerprint()] = candidateMatch } -func sortFixedVersions(candidateMatch match.Match, p pkg.Package) { - if len(candidateMatch.Vulnerability.Fix.Versions) <= 1 { - return - } - - format := version.FormatFromPkg(p) - parseConstraint := func(constStr string) (version.Constraint, error) { - constraint, err := version.GetConstraint(constStr, format) - if err != nil { - log.WithFields("package", p.Name).Trace("skipping sorting fixed versions") - } - return constraint, err - } - - checkSatisfaction := func(constraint version.Constraint, v *version.Version) bool { - satisfied, err := constraint.Satisfied(v) - if err != nil { - log.WithFields("package", p.Name).Trace("error while checking version satisfaction for sorting") - } - return satisfied && err == nil - } - - sort.SliceStable(candidateMatch.Vulnerability.Fix.Versions, func(i, j int) bool { - v1, err1 := version.NewVersion(candidateMatch.Vulnerability.Fix.Versions[i], format) - v2, err2 := version.NewVersion(candidateMatch.Vulnerability.Fix.Versions[j], format) - if err1 != nil || err2 != nil { - log.WithFields("package", p.Name).Trace("error while parsing version for sorting") - return false - } - - packageConstraint, err := parseConstraint(fmt.Sprintf("<=%s", candidateMatch.Package.Version)) - if err != nil { - return false - } - - v1Satisfied := checkSatisfaction(packageConstraint, v1) - v2Satisfied := checkSatisfaction(packageConstraint, v2) - - if v1Satisfied != v2Satisfied { - return !v1Satisfied - } - - internalConstraint, err := parseConstraint(fmt.Sprintf("<=%s", v1.Raw)) - if err != nil { - return false - } - return !checkSatisfaction(internalConstraint, v2) - }) -} - func addMatchDetails(existingDetails []match.Detail, newDetails match.Detail) []match.Detail { newFound, ok := newDetails.Found.(CPEResult) if !ok {