From 6836892e0ae7f8555f60ce06876467e00d6a66a1 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Tue, 14 Jan 2025 16:58:44 -0500 Subject: [PATCH 1/3] fix: disregard RPM module build number in version comparison Previously, different build numbers of the same RPM version release string were compared lexicographically, leading to incorrect comparisons between RedHat and RedHat clone RPMs, resulting in FPs or FNs on centOS. Signed-off-by: Will Murphy --- grype/version/rpm_version.go | 27 ++++++++++++++++++++++++++- grype/version/rpm_version_test.go | 5 ++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/grype/version/rpm_version.go b/grype/version/rpm_version.go index af77467fac6..5e8b949a525 100644 --- a/grype/version/rpm_version.go +++ b/grype/version/rpm_version.go @@ -101,7 +101,32 @@ func (v rpmVersion) compare(v2 rpmVersion) int { return ret } - return compareRpmVersions(v.release, v2.release) + return compareRpmReleases(v.release, v2.release) +} + +// compareRpmReleases normalizes two release strigns before +// calling compareRpmVersions to compare them. +// It normalize the release strings by removing the build number +// from the end: +// "1.module_el8.3.0+757+d382997d" -> "1.module_el8.3.0" +// This is important because the build numbers are not identical between CentOS +// 8 and RHEL 8, even for the same package version, leading to FPs or FNs. +func compareRpmReleases(a, b string) int { + if a == b { + return 0 + } + + aParts := strings.Split(a, "+") + bParts := strings.Split(b, "+") + if len(aParts) > 2 { + aParts = aParts[:len(aParts)-2] + } + if len(bParts) > 2 { + bParts = bParts[:len(bParts)-2] + } + trimmedA := strings.Join(aParts, "+") + trimmedB := strings.Join(bParts, "+") + return compareRpmVersions(trimmedA, trimmedB) } func epochIsPresent(epoch *int) bool { diff --git a/grype/version/rpm_version_test.go b/grype/version/rpm_version_test.go index 4997b021ce8..f0ae410c20d 100644 --- a/grype/version/rpm_version_test.go +++ b/grype/version/rpm_version_test.go @@ -25,12 +25,15 @@ func TestVersionRpm(t *testing.T) { {"1:2", "1", 1}, {"0:4.19.1-1.el7_5", "2:4.19.1-1.el7_5", -1}, {"4:1.2.3-3-el7_5", "1.2.3-el7_5~snapshot1", 1}, - //Non-standard comparisons that ignore epochs due to only one being available + // Non-standard comparisons that ignore epochs due to only one being available {"1:0", "1", -1}, {"2:4.19.01-1.el7_5", "4.19.1-1.el7_5", 0}, {"4.19.01-1.el7_5", "2:4.19.1-1.el7_5", 0}, {"4.19.0-1.el7_5", "12:4.19.0-1.el7", 1}, {"3:4.19.0-1.el7_5", "4.21.0-1.el7", -1}, + // centos and rhel build numbers differ on same version of same package + // ensure these are equal. + {"3:10.3.28-1.module_el8.3.0+757+d382997d", "3:10.3.28-1.module+el8.3.0+10472+7adc332a", 0}, } for _, test := range tests { From ca4a246a4bc5e5638c466dd721ca1647b11a7c48 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Thu, 13 Feb 2025 11:20:00 -0500 Subject: [PATCH 2/3] fix: account for N plus signs in rpm release string Also, add more test cases from different distros. Signed-off-by: Will Murphy --- grype/version/rpm_version.go | 15 +++++---------- grype/version/rpm_version_test.go | 7 +++++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/grype/version/rpm_version.go b/grype/version/rpm_version.go index 5e8b949a525..f75676c9dab 100644 --- a/grype/version/rpm_version.go +++ b/grype/version/rpm_version.go @@ -116,16 +116,11 @@ func compareRpmReleases(a, b string) int { return 0 } - aParts := strings.Split(a, "+") - bParts := strings.Split(b, "+") - if len(aParts) > 2 { - aParts = aParts[:len(aParts)-2] - } - if len(bParts) > 2 { - bParts = bParts[:len(bParts)-2] - } - trimmedA := strings.Join(aParts, "+") - trimmedB := strings.Join(bParts, "+") + a = strings.Replace(a, "module+el", "module_el", 1) + b = strings.Replace(b, "module+el", "module_el", 1) + + trimmedA, _, _ := strings.Cut(a, "+") + trimmedB, _, _ := strings.Cut(b, "+") return compareRpmVersions(trimmedA, trimmedB) } diff --git a/grype/version/rpm_version_test.go b/grype/version/rpm_version_test.go index f0ae410c20d..cc73acb4253 100644 --- a/grype/version/rpm_version_test.go +++ b/grype/version/rpm_version_test.go @@ -34,6 +34,13 @@ func TestVersionRpm(t *testing.T) { // centos and rhel build numbers differ on same version of same package // ensure these are equal. {"3:10.3.28-1.module_el8.3.0+757+d382997d", "3:10.3.28-1.module+el8.3.0+10472+7adc332a", 0}, + // some amazonlinux examples + {"2.13.0-2.amzn2023.0.2", "2.13.0-2.amzn2023.0.1", 1}, + {"1.20.14-18.amzn2023.0.1", "1.20.14-18.amzn2023.0.2", -1}, + // examples from oracle linux 8 for python38-tkinter ELSA-2021-9130 + {"3.8.17-2.module+el8.9.0+90017+9913aa0c", "0:3.8.3-3.0.1.module+el8.3.0+el8+9681+09f2c1ca", 1}, + // note that build number 9680 and 9681 are different, but that's not part of the version comparison + {"0:3.8.3-3.0.1.module+el8.3.0+el8+9680+09f2c1ca", "0:3.8.3-3.0.1.module+el8.3.0+el8+9681+09f2c1ca", 0}, } for _, test := range tests { From 736220a14d58e41c3144cb3385d30d7968846628 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Thu, 13 Feb 2025 12:10:59 -0500 Subject: [PATCH 3/3] chore: bump vulnerability match labels Signed-off-by: Will Murphy --- test/quality/vulnerability-match-labels | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/quality/vulnerability-match-labels b/test/quality/vulnerability-match-labels index 8915ebaa906..cbe008df99a 160000 --- a/test/quality/vulnerability-match-labels +++ b/test/quality/vulnerability-match-labels @@ -1 +1 @@ -Subproject commit 8915ebaa90638c15512afa1299a5cc4015d6a3b5 +Subproject commit cbe008df99ae4531767eddf1f36dce17f2434c4b