From 8ea308a0eed448de3b78cdc9ea06b3d51e10ed9a Mon Sep 17 00:00:00 2001 From: Christopher Phillips Date: Tue, 15 Aug 2023 12:00:26 -0400 Subject: [PATCH 1/6] fix: update semver constraint to allow 1.20rc1 cases Signed-off-by: Christopher Phillips --- grype/version/fuzzy_constraint.go | 2 +- grype/version/fuzzy_constraint_test.go | 23 +++++++++++++++++++++++ grype/version/semantic_constraint_test.go | 8 +++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/grype/version/fuzzy_constraint.go b/grype/version/fuzzy_constraint.go index abda758d501..7e4428d47d9 100644 --- a/grype/version/fuzzy_constraint.go +++ b/grype/version/fuzzy_constraint.go @@ -9,7 +9,7 @@ import ( ) // derived from https://semver.org/, but additionally matches partial versions (e.g. "2.0") -var pseudoSemverPattern = regexp.MustCompile(`^(0|[1-9]\d*)(\.(0|[1-9]\d*))?(\.(0|[1-9]\d*))?(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`) +var pseudoSemverPattern = regexp.MustCompile(`^(0|[1-9]\d*)(\.(0|[1-9]\d*))?(\.(0|[1-9]\d*))?((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`) type fuzzyConstraint struct { rawPhrase string diff --git a/grype/version/fuzzy_constraint_test.go b/grype/version/fuzzy_constraint_test.go index 150a383e30e..959105c0cda 100644 --- a/grype/version/fuzzy_constraint_test.go +++ b/grype/version/fuzzy_constraint_test.go @@ -264,6 +264,12 @@ func TestFuzzyConstraintSatisfaction(t *testing.T) { constraint: "> v1.5", satisfied: true, }, + { + name: "rc candidates with no '-' can match semver pattern", + version: "1.20rc1", + constraint: " = 1.20.0-rc1", + satisfied: true, + }, } for _, test := range tests { @@ -275,3 +281,20 @@ func TestFuzzyConstraintSatisfaction(t *testing.T) { }) } } + +func TestPseudoSemverPattern(t *testing.T) { + tests := []struct { + name string + version string + valid bool + }{ + {name: "rc candidates are valid semver", version: "1.2.3-rc1", valid: true}, + {name: "rc candidates with no dash are valid semver", version: "1.2.3rc1", valid: true}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.valid, pseudoSemverPattern.MatchString(test.version)) + }) + } +} diff --git a/grype/version/semantic_constraint_test.go b/grype/version/semantic_constraint_test.go index 42f36711c80..17adb68bb6a 100644 --- a/grype/version/semantic_constraint_test.go +++ b/grype/version/semantic_constraint_test.go @@ -70,6 +70,12 @@ func TestVersionSemantic(t *testing.T) { {version: "1.0.0-beta.11", constraint: "< 1.0.0-rc.1", satisfied: true}, {version: "1.0.0-rc.1", constraint: "> 1.0.0", satisfied: false}, {version: "1.0.0-rc.1", constraint: "< 1.0.0", satisfied: true}, + {version: "1.20rc1", constraint: " = 1.20.0-rc1", satisfied: true}, + {version: "1.21rc2", constraint: " = 1.21.1", satisfied: false}, + {version: "1.21rc2", constraint: " = 1.21", satisfied: false}, + {version: "1.21rc2", constraint: " = 1.21-rc2", satisfied: true}, + {version: "1.21rc2", constraint: " = 1.21.0-rc2", satisfied: true}, + {version: "1.21rc2", constraint: " = 1.21.0rc2", satisfied: true}, {version: "1.0.0-alpha.1", constraint: "> 1.0.0-alpha.1", satisfied: false}, {version: "1.0.0-alpha.2", constraint: "> 1.0.0-alpha.1", satisfied: true}, {version: "1.2.0-beta", constraint: ">1.0, <2.0", satisfied: true}, @@ -79,7 +85,7 @@ func TestVersionSemantic(t *testing.T) { } for _, test := range tests { - t.Run(test.tName(), func(t *testing.T) { + t.Run(test.name, func(t *testing.T) { constraint, err := newSemanticConstraint(test.constraint) assert.NoError(t, err, "unexpected error from newSemanticConstraint: %v", err) From b9a48bd06ec1acf48a290ccfad41d09e4e5b480b Mon Sep 17 00:00:00 2001 From: Christopher Phillips Date: Tue, 15 Aug 2023 12:31:58 -0400 Subject: [PATCH 2/6] test: add constraints for python and openssl cases Signed-off-by: Christopher Phillips --- grype/version/fuzzy_constraint_test.go | 48 ++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/grype/version/fuzzy_constraint_test.go b/grype/version/fuzzy_constraint_test.go index 959105c0cda..22b39a116be 100644 --- a/grype/version/fuzzy_constraint_test.go +++ b/grype/version/fuzzy_constraint_test.go @@ -270,6 +270,54 @@ func TestFuzzyConstraintSatisfaction(t *testing.T) { constraint: " = 1.20.0-rc1", satisfied: true, }, + { + name: "candidates ahead of alpha are satisfied", + version: "3.11.0", + constraint: "> 3.11.0-alpha1", + satisfied: true, + }, + { + name: "candidates ahead of beta are satisfied", + version: "3.11.0", + constraint: "> 3.11.0-beta1", + satisfied: true, + }, + { + name: "candidates ahead of same alpha versions are satisfied", + version: "3.11.0-alpha5", + constraint: "> 3.11.0-alpha1", + satisfied: true, + }, + { + name: "candidates between alpha and release are not satisfied", + version: "3.11.0-beta5", + constraint: "3.11.0 || = 3.11.0-alpha1", + satisfied: false, + }, + { + name: "candidates are greater than their a versions and satisfied", + version: "1.0.2", + constraint: "> 1.0.2a", + satisfied: true, + }, + { + name: "candidates with letter suffix are alphabetically greater than their versions and satisfied", + version: "1.0.2a", + constraint: " < 1.0.2w", + satisfied: true, + }, + { + name: "candidates with multiple letter suffix are alphabetically greater than their versions and satisfied", + version: "1.0.2zg", + constraint: " < 1.0.2zh", + satisfied: true, + }, + { + name: "candidates with pre suffix are sorted numerically and satisfied", + version: "1.0.2pre1", + constraint: " < 1.0.2pre2", + satisfied: true, + }, } for _, test := range tests { From 78d7f3c9b0c29dc7891780efdb75a5c49f6fa731 Mon Sep 17 00:00:00 2001 From: Christopher Phillips Date: Tue, 15 Aug 2023 13:06:20 -0400 Subject: [PATCH 3/6] test: add failing openssl cases Signed-off-by: Christopher Phillips --- grype/version/fuzzy_constraint_test.go | 34 ++++++++++++++++++++------ 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/grype/version/fuzzy_constraint_test.go b/grype/version/fuzzy_constraint_test.go index 22b39a116be..2dc9f550d24 100644 --- a/grype/version/fuzzy_constraint_test.go +++ b/grype/version/fuzzy_constraint_test.go @@ -271,53 +271,71 @@ func TestFuzzyConstraintSatisfaction(t *testing.T) { satisfied: true, }, { - name: "candidates ahead of alpha are satisfied", + name: "candidates ahead of alpha", version: "3.11.0", constraint: "> 3.11.0-alpha1", satisfied: true, }, { - name: "candidates ahead of beta are satisfied", + name: "candidates ahead of beta", version: "3.11.0", constraint: "> 3.11.0-beta1", satisfied: true, }, { - name: "candidates ahead of same alpha versions are satisfied", + name: "candidates ahead of same alpha versions", version: "3.11.0-alpha5", constraint: "> 3.11.0-alpha1", satisfied: true, }, { - name: "candidates between alpha and release are not satisfied", + name: "candidates are placed correctly between alpha and release", version: "3.11.0-beta5", constraint: "3.11.0 || = 3.11.0-alpha1", satisfied: false, }, { - name: "candidates are greater than their a versions and satisfied", + name: "candidates are greater than their a versions", version: "1.0.2", constraint: "> 1.0.2a", satisfied: true, }, { - name: "candidates with letter suffix are alphabetically greater than their versions and satisfied", + name: "candidates with letter suffix are alphabetically greater than their versions", version: "1.0.2a", constraint: " < 1.0.2w", satisfied: true, }, { - name: "candidates with multiple letter suffix are alphabetically greater than their versions and satisfied", + name: "candidates with multiple letter suffix are alphabetically greater than their versions", version: "1.0.2zg", constraint: " < 1.0.2zh", satisfied: true, }, { - name: "candidates with pre suffix are sorted numerically and satisfied", + name: "candidates with pre suffix are sorted numerically", version: "1.0.2pre1", constraint: " < 1.0.2pre2", satisfied: true, }, + { + name: "candidates with letter suffix and r0 are alphabetically greater than their versions", + version: "1.0.2k-r0", + constraint: " < 1.0.2l-r0", + satisfied: true, + }, + { + name: "openssl version with letter suffix and r0 are alphabetically greater than their versions", + version: "1.0.2k-r0", + constraint: ">= 1.0.2", + satisfied: true, + }, + { + name: "foobar", + version: "1.0.2k-r0", + constraint: ">= 1.0.2, < 1.0.2m", + satisfied: true, + }, } for _, test := range tests { From 7d173b35ef937f20b0460a6c2e25ae0211ba4040 Mon Sep 17 00:00:00 2001 From: Christopher Phillips Date: Tue, 15 Aug 2023 13:29:35 -0400 Subject: [PATCH 4/6] fix: update constraint to be more specific to suffix Signed-off-by: Christopher Phillips --- grype/version/fuzzy_constraint.go | 2 +- grype/version/fuzzy_constraint_test.go | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/grype/version/fuzzy_constraint.go b/grype/version/fuzzy_constraint.go index 7e4428d47d9..77d788332cf 100644 --- a/grype/version/fuzzy_constraint.go +++ b/grype/version/fuzzy_constraint.go @@ -9,7 +9,7 @@ import ( ) // derived from https://semver.org/, but additionally matches partial versions (e.g. "2.0") -var pseudoSemverPattern = regexp.MustCompile(`^(0|[1-9]\d*)(\.(0|[1-9]\d*))?(\.(0|[1-9]\d*))?((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`) +var pseudoSemverPattern = regexp.MustCompile(`^(0|[1-9]\d*)(\.(0|[1-9]\d*))?(\.(0|[1-9]\d*))?(?:(-|alpha|beta|rc)((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`) type fuzzyConstraint struct { rawPhrase string diff --git a/grype/version/fuzzy_constraint_test.go b/grype/version/fuzzy_constraint_test.go index 2dc9f550d24..348caa8c93a 100644 --- a/grype/version/fuzzy_constraint_test.go +++ b/grype/version/fuzzy_constraint_test.go @@ -294,12 +294,6 @@ func TestFuzzyConstraintSatisfaction(t *testing.T) { constraint: "3.11.0 || = 3.11.0-alpha1", satisfied: false, }, - { - name: "candidates are greater than their a versions", - version: "1.0.2", - constraint: "> 1.0.2a", - satisfied: true, - }, { name: "candidates with letter suffix are alphabetically greater than their versions", version: "1.0.2a", @@ -336,6 +330,18 @@ func TestFuzzyConstraintSatisfaction(t *testing.T) { constraint: ">= 1.0.2, < 1.0.2m", satisfied: true, }, + { + name: "foobar", + version: "1.1.1-pre2", + constraint: "> 1.1.1-pre1, < 1.1.1", + satisfied: true, + }, + { + name: "foobar", + version: "1.1.1", + constraint: "> 1.1.1-a", + satisfied: true, + }, } for _, test := range tests { From 271a2c254a54682903faf113f87c33e8ad867831 Mon Sep 17 00:00:00 2001 From: Christopher Phillips Date: Tue, 15 Aug 2023 13:34:38 -0400 Subject: [PATCH 5/6] test: update test names Signed-off-by: Christopher Phillips --- grype/version/fuzzy_constraint_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grype/version/fuzzy_constraint_test.go b/grype/version/fuzzy_constraint_test.go index 348caa8c93a..3be6292d469 100644 --- a/grype/version/fuzzy_constraint_test.go +++ b/grype/version/fuzzy_constraint_test.go @@ -325,19 +325,19 @@ func TestFuzzyConstraintSatisfaction(t *testing.T) { satisfied: true, }, { - name: "foobar", + name: "openssl versions with letter suffix and r0 are alphabetically greater than their versions and compared equally to other lettered versions", version: "1.0.2k-r0", constraint: ">= 1.0.2, < 1.0.2m", satisfied: true, }, { - name: "foobar", + name: "openssl pre2 is still considered less than release", version: "1.1.1-pre2", constraint: "> 1.1.1-pre1, < 1.1.1", satisfied: true, }, { - name: "foobar", + name: "major version releases are less than their subsequent patch releases with letter suffixes", version: "1.1.1", constraint: "> 1.1.1-a", satisfied: true, From 9ccdf47873448590112b547bfef8ca50dbfc0d89 Mon Sep 17 00:00:00 2001 From: Christopher Phillips Date: Tue, 15 Aug 2023 13:37:00 -0400 Subject: [PATCH 6/6] revert: revert test name field Signed-off-by: Christopher Phillips --- grype/version/semantic_constraint_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grype/version/semantic_constraint_test.go b/grype/version/semantic_constraint_test.go index 17adb68bb6a..43dae2f2c42 100644 --- a/grype/version/semantic_constraint_test.go +++ b/grype/version/semantic_constraint_test.go @@ -85,7 +85,7 @@ func TestVersionSemantic(t *testing.T) { } for _, test := range tests { - t.Run(test.name, func(t *testing.T) { + t.Run(test.tName(), func(t *testing.T) { constraint, err := newSemanticConstraint(test.constraint) assert.NoError(t, err, "unexpected error from newSemanticConstraint: %v", err)