Skip to content

Commit 0242bcc

Browse files
committed
fix: implement combineVersionAndUpdate function for version handling
- Added a new function `combineVersionAndUpdate` to handle the combination of version and update fields for various package types. - Updated the `MatchPackageByCPEs` and `filterCPEsByVersion` functions to utilize the new logic, ensuring consistent version formatting across non-JVM and JVM packages. Signed-off-by: [email protected] <[email protected]> Signed-off-by: ayham291 <[email protected]>
1 parent e5e784d commit 0242bcc

File tree

2 files changed

+120
-8
lines changed

2 files changed

+120
-8
lines changed

grype/matcher/internal/cpe.go

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,8 @@ func MatchPackageByCPEs(provider vulnerability.Provider, p pkg.Package, upstream
7070

7171
format := pkg.VersionFormat(p)
7272

73-
if format == version.JVMFormat {
74-
searchVersion = transformJvmVersion(searchVersion, c.Attributes.Update)
75-
}
73+
// Apply version and update field combination for all package types
74+
searchVersion = combineVersionAndUpdate(searchVersion, c.Attributes.Update, format)
7675

7776
var verObj *version.Version
7877
var err error
@@ -111,6 +110,27 @@ func transformJvmVersion(searchVersion, updateCpeField string) string {
111110
return searchVersion
112111
}
113112

113+
func combineVersionAndUpdate(searchVersion, updateCpeField string, format version.Format) string {
114+
// Handle empty or wildcard update fields
115+
if updateCpeField == "" || updateCpeField == wfn.NA || updateCpeField == wfn.Any {
116+
return searchVersion
117+
}
118+
119+
// Don't combine if the version is empty or a wildcard - these should remain as is
120+
if searchVersion == "" || searchVersion == wfn.NA || searchVersion == wfn.Any {
121+
return searchVersion
122+
}
123+
124+
// Special handling for JVM packages
125+
if format == version.JVMFormat {
126+
return transformJvmVersion(searchVersion, updateCpeField)
127+
}
128+
129+
// For other packages, combine version and update field directly
130+
// This handles cases like NTP where version="4.2.8" and update="p18" should become "4.2.8p18"
131+
return fmt.Sprintf("%s%s", searchVersion, updateCpeField)
132+
}
133+
114134
func addNewMatch(matchesByFingerprint map[match.Fingerprint]match.Match, vuln vulnerability.Vulnerability, p pkg.Package, searchVersion *version.Version, upstreamMatcher match.MatcherType, searchedByCPE cpe.CPE) {
115135
candidateMatch := match.Match{
116136

@@ -205,11 +225,8 @@ func filterCPEsByVersion(pkgVersion *version.Version, allCPEs []cpe.CPE) (matche
205225

206226
ver := c.Attributes.Version
207227

208-
if pkgVersion.Format == version.JVMFormat {
209-
if c.Attributes.Update != wfn.Any && c.Attributes.Update != wfn.NA {
210-
ver = transformJvmVersion(ver, c.Attributes.Update)
211-
}
212-
}
228+
// Apply version and update field combination for all package types
229+
ver = combineVersionAndUpdate(ver, c.Attributes.Update, pkgVersion.Format)
213230

214231
constraint, err := version.GetConstraint(ver, pkgVersion.Format)
215232
if err != nil {

grype/matcher/internal/cpe_test.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,101 @@ func TestFilterCPEsByVersion(t *testing.T) {
10821082
}
10831083
}
10841084

1085+
func TestCombineVersionAndUpdate(t *testing.T) {
1086+
tests := []struct {
1087+
name string
1088+
searchVersion string
1089+
updateCpeField string
1090+
format version.Format
1091+
expectedVersion string
1092+
}{
1093+
{
1094+
name: "non-JVM package with update field (NTP example)",
1095+
searchVersion: "4.2.8",
1096+
updateCpeField: "p18",
1097+
format: version.UnknownFormat,
1098+
expectedVersion: "4.2.8p18",
1099+
},
1100+
{
1101+
name: "non-JVM package without update field",
1102+
searchVersion: "1.2.3",
1103+
updateCpeField: "",
1104+
format: version.UnknownFormat,
1105+
expectedVersion: "1.2.3",
1106+
},
1107+
{
1108+
name: "non-JVM package with Any update field",
1109+
searchVersion: "1.2.3",
1110+
updateCpeField: "",
1111+
format: version.UnknownFormat,
1112+
expectedVersion: "1.2.3",
1113+
},
1114+
{
1115+
name: "non-JVM package with NA update field",
1116+
searchVersion: "1.2.3",
1117+
updateCpeField: "-",
1118+
format: version.UnknownFormat,
1119+
expectedVersion: "1.2.3",
1120+
},
1121+
{
1122+
name: "JVM package with update field",
1123+
searchVersion: "1.8.0",
1124+
updateCpeField: "update400",
1125+
format: version.JVMFormat,
1126+
expectedVersion: "1.8.0_400",
1127+
},
1128+
{
1129+
name: "JVM package without update field (Any)",
1130+
searchVersion: "1.8.0",
1131+
updateCpeField: "",
1132+
format: version.JVMFormat,
1133+
expectedVersion: "1.8.0",
1134+
},
1135+
{
1136+
name: "JVM package without update field (NA)",
1137+
searchVersion: "1.8.0",
1138+
updateCpeField: "-",
1139+
format: version.JVMFormat,
1140+
expectedVersion: "1.8.0",
1141+
},
1142+
{
1143+
name: "semantic package with patch update",
1144+
searchVersion: "2.4.1",
1145+
updateCpeField: "rc1",
1146+
format: version.SemanticFormat,
1147+
expectedVersion: "2.4.1rc1",
1148+
},
1149+
{
1150+
name: "debian package with update",
1151+
searchVersion: "1.0.0",
1152+
updateCpeField: "deb1",
1153+
format: version.DebFormat,
1154+
expectedVersion: "1.0.0deb1",
1155+
},
1156+
{
1157+
name: "non-JVM package with wildcard version should not combine",
1158+
searchVersion: "",
1159+
updateCpeField: "update123",
1160+
format: version.UnknownFormat,
1161+
expectedVersion: "",
1162+
},
1163+
{
1164+
name: "non-JVM package with NA version should not combine",
1165+
searchVersion: "-",
1166+
updateCpeField: "update123",
1167+
format: version.UnknownFormat,
1168+
expectedVersion: "-",
1169+
},
1170+
}
1171+
1172+
for _, test := range tests {
1173+
t.Run(test.name, func(t *testing.T) {
1174+
result := combineVersionAndUpdate(test.searchVersion, test.updateCpeField, test.format)
1175+
assert.Equal(t, test.expectedVersion, result)
1176+
})
1177+
}
1178+
}
1179+
10851180
func TestAddMatchDetails(t *testing.T) {
10861181
tests := []struct {
10871182
name string

0 commit comments

Comments
 (0)