add FixedInVersions to check affected packages
Signed-off-by: liang chenye <liangchenye@huawei.com>
This commit is contained in:
parent
f1498b1d17
commit
cb42892716
@ -144,7 +144,7 @@ Server: clair
|
||||
"Description": "The parse_datetime function in GNU coreutils allows remote attackers to cause a denial of service (crash) or possibly execute arbitrary code via a crafted date string, as demonstrated by the \"--date=TZ=\"123\"345\" @1\" string to the touch or date command.",
|
||||
"Link": "https://security-tracker.debian.org/tracker/CVE-2014-9471",
|
||||
"Severity": "Low",
|
||||
"FixedBy": "9.23-5"
|
||||
"FixedBy": ">= 9.23-5"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -289,7 +289,7 @@ POST http://localhost:6060/v1/namespaces/debian%3A8/vulnerabilities HTTP/1.1
|
||||
{
|
||||
"Name": "coreutils",
|
||||
"NamespaceName": "debian:8",
|
||||
"Version": "8.23-1"
|
||||
"FixedInVersions": ">= 8.23-1"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -322,7 +322,7 @@ Server: clair
|
||||
{
|
||||
"Name": "coreutils",
|
||||
"NamespaceName": "debian:8",
|
||||
"Version": "8.23-1"
|
||||
"FixedInVersions": ">= 8.23-1"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -373,7 +373,7 @@ Server: clair
|
||||
{
|
||||
"Name": "coreutils",
|
||||
"NamespaceName": "debian:8",
|
||||
"Version": "8.23-1"
|
||||
"FixedInVersions": ">= 8.23-1"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -592,7 +592,7 @@ Server: clair
|
||||
{
|
||||
"Name": "grep",
|
||||
"NamespaceName": "debian:8",
|
||||
"Version": "2.25"
|
||||
"FixedInVersions": ">= 2.25"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -77,7 +77,7 @@ func LayerFromDatabaseModel(dbLayer database.Layer, withFeatures, withVulnerabil
|
||||
Metadata: dbVuln.Metadata,
|
||||
}
|
||||
|
||||
if dbVuln.FixedBy != types.MaxVersion {
|
||||
if dbVuln.FixedBy.String() != types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MaxVersion).String() {
|
||||
vuln.FixedBy = dbVuln.FixedBy.String()
|
||||
}
|
||||
feature.Vulnerabilities = append(feature.Vulnerabilities, vuln)
|
||||
@ -154,31 +154,32 @@ type Feature struct {
|
||||
Name string `json:"Name,omitempty"`
|
||||
NamespaceName string `json:"NamespaceName,omitempty"`
|
||||
Version string `json:"Version,omitempty"`
|
||||
FixedInVersions string `json:"FixedInVersions,omitempty"`
|
||||
Vulnerabilities []Vulnerability `json:"Vulnerabilities,omitempty"`
|
||||
AddedBy string `json:"AddedBy,omitempty"`
|
||||
}
|
||||
|
||||
func FeatureFromDatabaseModel(dbFeatureVersion database.FeatureVersion) Feature {
|
||||
versionStr := dbFeatureVersion.Version.String()
|
||||
if versionStr == types.MaxVersion.String() {
|
||||
versionStr = "None"
|
||||
fixedInVersionsStr := dbFeatureVersion.FixedInVersions.String()
|
||||
if fixedInVersionsStr == types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MaxVersion).String() {
|
||||
fixedInVersionsStr = "None"
|
||||
}
|
||||
|
||||
return Feature{
|
||||
Name: dbFeatureVersion.Feature.Name,
|
||||
NamespaceName: dbFeatureVersion.Feature.Namespace.Name,
|
||||
Version: versionStr,
|
||||
AddedBy: dbFeatureVersion.AddedBy.Name,
|
||||
Name: dbFeatureVersion.Feature.Name,
|
||||
NamespaceName: dbFeatureVersion.Feature.Namespace.Name,
|
||||
FixedInVersions: fixedInVersionsStr,
|
||||
AddedBy: dbFeatureVersion.AddedBy.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func (f Feature) DatabaseModel() (database.FeatureVersion, error) {
|
||||
var version types.Version
|
||||
if f.Version == "None" {
|
||||
version = types.MaxVersion
|
||||
var fivs types.FixedInVersions
|
||||
if f.FixedInVersions == "None" {
|
||||
fivs = types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MaxVersion)
|
||||
} else {
|
||||
var err error
|
||||
version, err = types.NewVersion(f.Version)
|
||||
fivs, err = types.NewFixedInVersions(f.FixedInVersions)
|
||||
if err != nil {
|
||||
return database.FeatureVersion{}, err
|
||||
}
|
||||
@ -189,7 +190,7 @@ func (f Feature) DatabaseModel() (database.FeatureVersion, error) {
|
||||
Name: f.Name,
|
||||
Namespace: database.Namespace{Name: f.NamespaceName},
|
||||
},
|
||||
Version: version,
|
||||
FixedInVersions: fivs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -53,9 +53,10 @@ type Feature struct {
|
||||
type FeatureVersion struct {
|
||||
Model
|
||||
|
||||
Feature Feature
|
||||
Version types.Version
|
||||
AffectedBy []Vulnerability
|
||||
Feature Feature
|
||||
Version types.Version
|
||||
FixedInVersions types.FixedInVersions
|
||||
AffectedBy []Vulnerability
|
||||
|
||||
// For output purposes. Only make sense when the feature version is in the context of an image.
|
||||
AddedBy Layer
|
||||
@ -78,7 +79,7 @@ type Vulnerability struct {
|
||||
|
||||
// For output purposes. Only make sense when the vulnerability
|
||||
// is already about a specific Feature/FeatureVersion.
|
||||
FixedBy types.Version `json:",omitempty"`
|
||||
FixedBy types.FixedInVersions `json:",omitempty"`
|
||||
}
|
||||
|
||||
type MetadataMap map[string]interface{}
|
||||
|
@ -85,8 +85,8 @@ func TestRaceAffects(t *testing.T) {
|
||||
Namespace: feature.Namespace,
|
||||
FixedIn: []database.FeatureVersion{
|
||||
{
|
||||
Feature: feature,
|
||||
Version: types.NewVersionUnsafe(strconv.Itoa(version)),
|
||||
Feature: feature,
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">=" + strconv.Itoa(version)),
|
||||
},
|
||||
},
|
||||
Severity: types.Unknown,
|
||||
@ -149,7 +149,9 @@ func TestRaceAffects(t *testing.T) {
|
||||
// Get expected affects.
|
||||
for i := numVulnerabilities; i > featureVersionVersion; i-- {
|
||||
for _, vulnerability := range vulnerabilities[i] {
|
||||
expectedAffectedNames = append(expectedAffectedNames, vulnerability.Name)
|
||||
if vulnerability.FixedIn[0].FixedInVersions.Affected(featureVersion.Version) {
|
||||
expectedAffectedNames = append(expectedAffectedNames, vulnerability.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ func (pgSQL *pgSQL) insertFeatureVersions(featureVersions []database.FeatureVers
|
||||
type vulnerabilityAffectsFeatureVersion struct {
|
||||
vulnerabilityID int
|
||||
fixedInID int
|
||||
fixedInVersion types.Version
|
||||
fixedInVersions types.FixedInVersions
|
||||
}
|
||||
|
||||
func linkFeatureVersionToVulnerabilities(tx *sql.Tx, featureVersion database.FeatureVersion) error {
|
||||
@ -210,14 +210,12 @@ func linkFeatureVersionToVulnerabilities(tx *sql.Tx, featureVersion database.Fea
|
||||
for rows.Next() {
|
||||
var affect vulnerabilityAffectsFeatureVersion
|
||||
|
||||
err := rows.Scan(&affect.fixedInID, &affect.vulnerabilityID, &affect.fixedInVersion)
|
||||
err := rows.Scan(&affect.fixedInID, &affect.vulnerabilityID, &affect.fixedInVersions)
|
||||
if err != nil {
|
||||
return handleError("searchVulnerabilityFixedInFeature.Scan()", err)
|
||||
}
|
||||
|
||||
if featureVersion.Version.Compare(affect.fixedInVersion) < 0 {
|
||||
// The version of the FeatureVersion we are inserting is lower than the fixed version on this
|
||||
// Vulnerability, thus, this FeatureVersion is affected by it.
|
||||
if affect.fixedInVersions.Affected(featureVersion.Version) {
|
||||
affects = append(affects, affect)
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ func TestFindLayer(t *testing.T) {
|
||||
assert.Equal(t, types.High, featureVersion.AffectedBy[0].Severity)
|
||||
assert.Equal(t, "A vulnerability affecting OpenSSL < 2.0 on Debian 7.0", featureVersion.AffectedBy[0].Description)
|
||||
assert.Equal(t, "http://google.com/#q=CVE-OPENSSL-1-DEB7", featureVersion.AffectedBy[0].Link)
|
||||
assert.Equal(t, types.NewVersionUnsafe("2.0"), featureVersion.AffectedBy[0].FixedBy)
|
||||
assert.Equal(t, types.NewFixedInVersionsUnsafe(">= 2.0").String(), featureVersion.AffectedBy[0].FixedBy.String())
|
||||
}
|
||||
default:
|
||||
t.Errorf("unexpected package %s for layer-1", featureVersion.Feature.Name)
|
||||
|
@ -104,8 +104,8 @@ func TestNotification(t *testing.T) {
|
||||
Severity: "Unknown",
|
||||
FixedIn: []database.FeatureVersion{
|
||||
{
|
||||
Feature: f1,
|
||||
Version: types.NewVersionUnsafe("1.0"),
|
||||
Feature: f1,
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 1.0"),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -164,12 +164,12 @@ func TestNotification(t *testing.T) {
|
||||
v1b.Severity = types.High
|
||||
v1b.FixedIn = []database.FeatureVersion{
|
||||
{
|
||||
Feature: f1,
|
||||
Version: types.MinVersion,
|
||||
Feature: f1,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MinVersion),
|
||||
},
|
||||
{
|
||||
Feature: f2,
|
||||
Version: types.MaxVersion,
|
||||
Feature: f2,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MaxVersion),
|
||||
},
|
||||
}
|
||||
|
||||
|
4
database/pgsql/testdata/data.sql
vendored
4
database/pgsql/testdata/data.sql
vendored
@ -48,8 +48,8 @@ INSERT INTO vulnerability (id, namespace_id, name, description, link, severity)
|
||||
(2, 1, 'CVE-NOPE', 'A vulnerability affecting nothing', '', 'Unknown');
|
||||
|
||||
INSERT INTO vulnerability_fixedin_feature (id, vulnerability_id, feature_id, version) VALUES
|
||||
(1, 1, 2, '2.0'),
|
||||
(2, 1, 4, '1.9-abc');
|
||||
(1, 1, 2, '>= 2.0'),
|
||||
(2, 1, 4, '>= 1.9-abc');
|
||||
|
||||
INSERT INTO vulnerability_affects_featureversion (id, vulnerability_id, featureversion_id, fixedin_id) VALUES
|
||||
(1, 1, 2, 1); -- CVE-OPENSSL-1-DEB7 affects Debian:7 OpenSSL 1.0
|
||||
|
@ -140,11 +140,11 @@ func scanVulnerability(queryer Queryer, queryName string, vulnerabilityRow *sql.
|
||||
|
||||
for rows.Next() {
|
||||
var featureVersionID zero.Int
|
||||
var featureVersionVersion zero.String
|
||||
var featureVersionFixedInVersions zero.String
|
||||
var featureVersionFeatureName zero.String
|
||||
|
||||
err := rows.Scan(
|
||||
&featureVersionVersion,
|
||||
&featureVersionFixedInVersions,
|
||||
&featureVersionID,
|
||||
&featureVersionFeatureName,
|
||||
)
|
||||
@ -163,7 +163,7 @@ func scanVulnerability(queryer Queryer, queryName string, vulnerabilityRow *sql.
|
||||
Namespace: vulnerability.Namespace,
|
||||
Name: featureVersionFeatureName.String,
|
||||
},
|
||||
Version: types.NewVersionUnsafe(featureVersionVersion.String),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(featureVersionFixedInVersions.String),
|
||||
}
|
||||
vulnerability.FixedIn = append(vulnerability.FixedIn, featureVersion)
|
||||
}
|
||||
@ -274,7 +274,7 @@ func (pgSQL *pgSQL) insertVulnerability(vulnerability database.Vulnerability, on
|
||||
// for diffing existing vulnerabilities.
|
||||
var fixedIn []database.FeatureVersion
|
||||
for _, fv := range vulnerability.FixedIn {
|
||||
if fv.Version != types.MinVersion {
|
||||
if fv.FixedInVersions.String() != types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MinVersion).String() {
|
||||
fixedIn = append(fixedIn, fv)
|
||||
}
|
||||
}
|
||||
@ -350,7 +350,7 @@ func applyFixedInDiff(currentList, diff []database.FeatureVersion) ([]database.F
|
||||
different := false
|
||||
|
||||
for _, name := range addedNames {
|
||||
if diffMap[name].Version == types.MinVersion {
|
||||
if diffMap[name].FixedInVersions.String() == types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MinVersion).String() {
|
||||
// MinVersion only makes sense when a Feature is already fixed in some version,
|
||||
// in which case we would be in the "inBothNames".
|
||||
continue
|
||||
@ -363,7 +363,7 @@ func applyFixedInDiff(currentList, diff []database.FeatureVersion) ([]database.F
|
||||
for _, name := range inBothNames {
|
||||
fv := diffMap[name]
|
||||
|
||||
if fv.Version == types.MinVersion {
|
||||
if fv.FixedInVersions.String() == types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MinVersion).String() {
|
||||
// MinVersion means that the Feature doesn't affect the Vulnerability anymore.
|
||||
delete(currentMap, name)
|
||||
different = true
|
||||
@ -438,7 +438,7 @@ func (pgSQL *pgSQL) insertVulnerabilityFixedInFeatureVersions(tx *sql.Tx, vulner
|
||||
err = tx.QueryRow(
|
||||
insertVulnerabilityFixedInFeature,
|
||||
vulnerabilityID, fv.Feature.ID,
|
||||
&fv.Version,
|
||||
&fv.FixedInVersions,
|
||||
).Scan(&fixedInID)
|
||||
|
||||
if err != nil {
|
||||
@ -446,7 +446,7 @@ func (pgSQL *pgSQL) insertVulnerabilityFixedInFeatureVersions(tx *sql.Tx, vulner
|
||||
}
|
||||
|
||||
// Insert Vulnerability_Affects_FeatureVersion.
|
||||
err = linkVulnerabilityToFeatureVersions(tx, fixedInID, vulnerabilityID, fv.Feature.ID, fv.Version)
|
||||
err = linkVulnerabilityToFeatureVersions(tx, fixedInID, vulnerabilityID, fv.Feature.ID, fv.FixedInVersions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -455,7 +455,7 @@ func (pgSQL *pgSQL) insertVulnerabilityFixedInFeatureVersions(tx *sql.Tx, vulner
|
||||
return nil
|
||||
}
|
||||
|
||||
func linkVulnerabilityToFeatureVersions(tx *sql.Tx, fixedInID, vulnerabilityID, featureID int, fixedInVersion types.Version) error {
|
||||
func linkVulnerabilityToFeatureVersions(tx *sql.Tx, fixedInID, vulnerabilityID, featureID int, fixedInVersions types.FixedInVersions) error {
|
||||
// Find every FeatureVersions of the Feature that the vulnerability affects.
|
||||
// TODO(Quentin-M): LIMIT
|
||||
rows, err := tx.Query(searchFeatureVersionByFeature, featureID)
|
||||
@ -472,10 +472,7 @@ func linkVulnerabilityToFeatureVersions(tx *sql.Tx, fixedInID, vulnerabilityID,
|
||||
if err != nil {
|
||||
return handleError("searchFeatureVersionByFeature.Scan()", err)
|
||||
}
|
||||
|
||||
if affected.Version.Compare(fixedInVersion) < 0 {
|
||||
// The version of the FeatureVersion is lower than the fixed version of this vulnerability,
|
||||
// thus, this FeatureVersion is affected by it.
|
||||
if fixedInVersions.Affected(affected.Version) {
|
||||
affecteds = append(affecteds, affected)
|
||||
}
|
||||
}
|
||||
@ -527,7 +524,7 @@ func (pgSQL *pgSQL) DeleteVulnerabilityFix(vulnerabilityNamespace, vulnerability
|
||||
Name: vulnerabilityNamespace,
|
||||
},
|
||||
},
|
||||
Version: types.MinVersion,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MinVersion),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -46,12 +46,12 @@ func TestFindVulnerability(t *testing.T) {
|
||||
Namespace: database.Namespace{Name: "debian:7"},
|
||||
FixedIn: []database.FeatureVersion{
|
||||
{
|
||||
Feature: database.Feature{Name: "openssl"},
|
||||
Version: types.NewVersionUnsafe("2.0"),
|
||||
Feature: database.Feature{Name: "openssl"},
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 2.0"),
|
||||
},
|
||||
{
|
||||
Feature: database.Feature{Name: "libssl"},
|
||||
Version: types.NewVersionUnsafe("1.9-abc"),
|
||||
Feature: database.Feature{Name: "libssl"},
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 1.9-abc"),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -114,50 +114,50 @@ func TestInsertVulnerability(t *testing.T) {
|
||||
Name: "TestInsertVulnerabilityFeatureVersion1",
|
||||
Namespace: n1,
|
||||
},
|
||||
Version: types.NewVersionUnsafe("1.0"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 1.0"),
|
||||
}
|
||||
f2 := database.FeatureVersion{
|
||||
Feature: database.Feature{
|
||||
Name: "TestInsertVulnerabilityFeatureVersion1",
|
||||
Namespace: n2,
|
||||
},
|
||||
Version: types.NewVersionUnsafe("1.0"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 1.0"),
|
||||
}
|
||||
f3 := database.FeatureVersion{
|
||||
Feature: database.Feature{
|
||||
Name: "TestInsertVulnerabilityFeatureVersion2",
|
||||
},
|
||||
Version: types.MaxVersion,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MaxVersion),
|
||||
}
|
||||
f4 := database.FeatureVersion{
|
||||
Feature: database.Feature{
|
||||
Name: "TestInsertVulnerabilityFeatureVersion2",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("1.4"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 1.4"),
|
||||
}
|
||||
f5 := database.FeatureVersion{
|
||||
Feature: database.Feature{
|
||||
Name: "TestInsertVulnerabilityFeatureVersion3",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("1.5"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 1.5"),
|
||||
}
|
||||
f6 := database.FeatureVersion{
|
||||
Feature: database.Feature{
|
||||
Name: "TestInsertVulnerabilityFeatureVersion4",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("0.1"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 0.1"),
|
||||
}
|
||||
f7 := database.FeatureVersion{
|
||||
Feature: database.Feature{
|
||||
Name: "TestInsertVulnerabilityFeatureVersion5",
|
||||
},
|
||||
Version: types.MaxVersion,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MaxVersion),
|
||||
}
|
||||
f8 := database.FeatureVersion{
|
||||
Feature: database.Feature{
|
||||
Name: "TestInsertVulnerabilityFeatureVersion5",
|
||||
},
|
||||
Version: types.MinVersion,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MinVersion),
|
||||
}
|
||||
|
||||
// Insert invalid vulnerabilities.
|
||||
|
@ -196,7 +196,7 @@ func parseDebianJSON(data *jsonData) (vulnerabilities []database.Vulnerability,
|
||||
Name: "debian:" + database.DebianReleasesMapping[releaseName],
|
||||
},
|
||||
},
|
||||
Version: version,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, version),
|
||||
}
|
||||
vulnerability.FixedIn = append(vulnerability.FixedIn, pkg)
|
||||
|
||||
|
@ -45,7 +45,7 @@ func TestDebianParser(t *testing.T) {
|
||||
Namespace: database.Namespace{Name: "debian:8"},
|
||||
Name: "aptdaemon",
|
||||
},
|
||||
Version: types.MaxVersion,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MaxVersion),
|
||||
},
|
||||
{
|
||||
Feature: database.Feature{
|
||||
@ -53,7 +53,7 @@ func TestDebianParser(t *testing.T) {
|
||||
|
||||
Name: "aptdaemon",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("1.1.1+bzr982-1"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 1.1.1+bzr982-1"),
|
||||
},
|
||||
}
|
||||
|
||||
@ -71,21 +71,21 @@ func TestDebianParser(t *testing.T) {
|
||||
Namespace: database.Namespace{Name: "debian:8"},
|
||||
Name: "aptdaemon",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("0.7.0"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 0.7.0"),
|
||||
},
|
||||
{
|
||||
Feature: database.Feature{
|
||||
Namespace: database.Namespace{Name: "debian:unstable"},
|
||||
Name: "aptdaemon",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("0.7.0"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 0.7.0"),
|
||||
},
|
||||
{
|
||||
Feature: database.Feature{
|
||||
Namespace: database.Namespace{Name: "debian:8"},
|
||||
Name: "asterisk",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("0.5.56"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 0.5.56"),
|
||||
},
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ func TestDebianParser(t *testing.T) {
|
||||
Namespace: database.Namespace{Name: "debian:8"},
|
||||
Name: "asterisk",
|
||||
},
|
||||
Version: types.MinVersion,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MinVersion),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,6 @@ const (
|
||||
cveURLPrefix = "http://cve.mitre.org/cgi-bin/cvename.cgi?name="
|
||||
updaterFlag = "nodejsUpdater"
|
||||
defaultNodejsVersion = "all"
|
||||
//Add a suffix when an advisory is fixed `after` a certain version.
|
||||
defaultVersionSuffix = "-1"
|
||||
)
|
||||
|
||||
var log = capnslog.NewPackageLogger("github.com/coreos/clair", "updater/fetchers/nodejs")
|
||||
@ -131,8 +129,10 @@ func parseNodejsAdvisories(advisories []nodejsAdvisory, latestUpdate string) (vu
|
||||
},
|
||||
},
|
||||
}
|
||||
if version, err := getAdvisoryVersion(advisory.PatchedVersions); err == nil {
|
||||
pkg.Version = version
|
||||
if fivs, err := types.NewFixedInVersions(advisory.PatchedVersions); err == nil {
|
||||
pkg.FixedInVersions = fivs
|
||||
} else {
|
||||
log.Warningf("could not parse nodejs patched version: '%s'.", err)
|
||||
}
|
||||
vulnerability.FixedIn = append(vulnerability.FixedIn, pkg)
|
||||
|
||||
@ -149,34 +149,5 @@ func parseNodejsAdvisories(advisories []nodejsAdvisory, latestUpdate string) (vu
|
||||
return
|
||||
}
|
||||
|
||||
// getAdvisoryVersion parses a string containing one or multiple version ranges
|
||||
// and returns upper-bound. By nature, this simplification may lead to false-positives
|
||||
func getAdvisoryVersion(fullVersion string) (types.Version, error) {
|
||||
fixedVersion := types.MinVersion
|
||||
|
||||
for _, version := range strings.Split(fullVersion, "||") {
|
||||
ovs := getOperVersions(version)
|
||||
for _, ov := range ovs {
|
||||
if ov.Oper == ">" {
|
||||
if curVersion, err := types.NewVersion(ov.Version + defaultVersionSuffix); err != nil {
|
||||
log.Warningf("could not parse package version '%s': %s. skipping", curVersion, err.Error())
|
||||
} else if curVersion.Compare(fixedVersion) > 0 {
|
||||
fixedVersion = curVersion
|
||||
}
|
||||
} else if ov.Oper == ">=" {
|
||||
if curVersion, err := types.NewVersion(ov.Version); err != nil {
|
||||
log.Warningf("could not parse package version '%s': %s. skipping", curVersion, err.Error())
|
||||
} else if curVersion.Compare(fixedVersion) > 0 {
|
||||
fixedVersion = curVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if fixedVersion != types.MinVersion {
|
||||
return fixedVersion, nil
|
||||
}
|
||||
return types.MaxVersion, cerrors.ErrNotFound
|
||||
}
|
||||
|
||||
// Clean deletes any allocated resources.
|
||||
func (fetcher *NodejsFetcher) Clean() {}
|
||||
|
@ -50,14 +50,14 @@ func TestNodejsParser(t *testing.T) {
|
||||
Namespace: database.Namespace{Name: "nodejs:" + defaultNodejsVersion},
|
||||
Name: "ldapauth",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("2.2.4" + defaultVersionSuffix),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe("> 2.2.4"),
|
||||
},
|
||||
{
|
||||
Feature: database.Feature{
|
||||
Namespace: database.Namespace{Name: "nodejs:" + defaultNodejsVersion},
|
||||
Name: "ldapauth-fork",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("2.3.3"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 2.3.3"),
|
||||
},
|
||||
}
|
||||
for _, expectedFeatureVersion := range expectedFeatureVersions {
|
||||
@ -73,7 +73,7 @@ func TestNodejsParser(t *testing.T) {
|
||||
Namespace: database.Namespace{Name: "nodejs:" + defaultNodejsVersion},
|
||||
Name: "hawk",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("4.1.1"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">=3.1.3 < 4.0.0 || >=4.1.1"),
|
||||
},
|
||||
}
|
||||
for _, expectedFeatureVersion := range expectedFeatureVersions {
|
||||
|
@ -1,76 +0,0 @@
|
||||
// Copyright 2016 clair authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nodejs
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type operVersion struct {
|
||||
Oper string
|
||||
Version string
|
||||
}
|
||||
|
||||
type ovState string
|
||||
|
||||
const (
|
||||
ovStateInit ovState = "init"
|
||||
ovStateOper ovState = "operation"
|
||||
ovStateVersion ovState = "version"
|
||||
)
|
||||
|
||||
func isOper(ch rune) bool {
|
||||
return ch == '>' || ch == '<' || ch == '='
|
||||
}
|
||||
|
||||
func getOperVersions(content string) (ovs []operVersion) {
|
||||
state := ovStateInit
|
||||
begin := 0
|
||||
var ov operVersion
|
||||
for i, ch := range content {
|
||||
if unicode.IsSpace(ch) {
|
||||
continue
|
||||
}
|
||||
switch state {
|
||||
case ovStateInit:
|
||||
if isOper(ch) {
|
||||
state = ovStateOper
|
||||
begin = i
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case ovStateOper:
|
||||
if !isOper(ch) {
|
||||
state = ovStateVersion
|
||||
ov.Oper = strings.TrimSpace(content[begin:i])
|
||||
begin = i
|
||||
}
|
||||
case ovStateVersion:
|
||||
if isOper(ch) {
|
||||
state = ovStateOper
|
||||
ov.Version = strings.TrimSpace(content[begin:i])
|
||||
ovs = append(ovs, ov)
|
||||
begin = i
|
||||
}
|
||||
}
|
||||
}
|
||||
if state == ovStateVersion {
|
||||
ov.Version = strings.TrimSpace(content[begin:len(content)])
|
||||
ovs = append(ovs, ov)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
// Copyright 2016 clair authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nodejs
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNodeVersion(t *testing.T) {
|
||||
invalid_version := "3.1.3 < 4.0.0 || >= "
|
||||
versions := strings.Split(invalid_version, "||")
|
||||
for _, version := range versions {
|
||||
ovs := getOperVersions(version)
|
||||
assert.Len(t, ovs, 0)
|
||||
}
|
||||
|
||||
valid_version := ">=3.1.3 < 4.0.0 || >=4.1.1"
|
||||
versions = strings.Split(valid_version, "||")
|
||||
for _, version := range versions {
|
||||
if strings.Contains(version, "4.1.1") {
|
||||
ovs := getOperVersions(version)
|
||||
assert.Len(t, ovs, 1)
|
||||
assert.Equal(t, ">=", ovs[0].Oper)
|
||||
assert.Equal(t, "4.1.1", ovs[0].Version)
|
||||
} else {
|
||||
ovs := getOperVersions(version)
|
||||
assert.Len(t, ovs, 2)
|
||||
|
||||
for _, ov := range ovs {
|
||||
if ov.Oper == ">=" {
|
||||
assert.Equal(t, "3.1.3", ov.Version)
|
||||
} else if ov.Oper == "<" {
|
||||
assert.Equal(t, "4.0.0", ov.Version)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -283,11 +283,13 @@ func toFeatureVersions(criteria criteria) []database.FeatureVersion {
|
||||
}
|
||||
} else if strings.Contains(c.Comment, " is earlier than ") {
|
||||
const prefixLen = len(" is earlier than ")
|
||||
var version types.Version
|
||||
featureVersion.Feature.Name = strings.TrimSpace(c.Comment[:strings.Index(c.Comment, " is earlier than ")])
|
||||
featureVersion.Version, err = types.NewVersion(c.Comment[strings.Index(c.Comment, " is earlier than ")+prefixLen:])
|
||||
version, err = types.NewVersion(c.Comment[strings.Index(c.Comment, " is earlier than ")+prefixLen:])
|
||||
if err != nil {
|
||||
log.Warningf("could not parse package version '%s': %s. skipping", c.Comment[strings.Index(c.Comment, " is earlier than ")+prefixLen:], err.Error())
|
||||
}
|
||||
featureVersion.FixedInVersions = types.NewFixedInVersionsFromOV(types.OpGreaterEqual, version)
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,7 +299,7 @@ func toFeatureVersions(criteria criteria) []database.FeatureVersion {
|
||||
continue
|
||||
}
|
||||
|
||||
if featureVersion.Feature.Namespace.Name != "" && featureVersion.Feature.Name != "" && featureVersion.Version.String() != "" {
|
||||
if featureVersion.Feature.Namespace.Name != "" && featureVersion.Feature.Name != "" && featureVersion.FixedInVersions.String() != "" {
|
||||
featureVersionParameters[featureVersion.Feature.Namespace.Name+":"+featureVersion.Feature.Name] = featureVersion
|
||||
} else {
|
||||
log.Warningf("could not determine a valid package from criterions: %v", criterions)
|
||||
|
@ -45,21 +45,21 @@ func TestRHELParser(t *testing.T) {
|
||||
Namespace: database.Namespace{Name: "centos:7"},
|
||||
Name: "xerces-c",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("3.1.1-7.el7_1"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 3.1.1-7.el7_1"),
|
||||
},
|
||||
{
|
||||
Feature: database.Feature{
|
||||
Namespace: database.Namespace{Name: "centos:7"},
|
||||
Name: "xerces-c-devel",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("3.1.1-7.el7_1"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 3.1.1-7.el7_1"),
|
||||
},
|
||||
{
|
||||
Feature: database.Feature{
|
||||
Namespace: database.Namespace{Name: "centos:7"},
|
||||
Name: "xerces-c-doc",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("3.1.1-7.el7_1"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 3.1.1-7.el7_1"),
|
||||
},
|
||||
}
|
||||
|
||||
@ -84,14 +84,14 @@ func TestRHELParser(t *testing.T) {
|
||||
Namespace: database.Namespace{Name: "centos:6"},
|
||||
Name: "firefox",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("38.1.0-1.el6_6"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 38.1.0-1.el6_6"),
|
||||
},
|
||||
{
|
||||
Feature: database.Feature{
|
||||
Namespace: database.Namespace{Name: "centos:7"},
|
||||
Name: "firefox",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("38.1.0-1.el7_1"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 38.1.0-1.el7_1"),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -368,7 +368,7 @@ func parseUbuntuCVE(fileContent io.Reader) (vulnerability database.Vulnerability
|
||||
Namespace: database.Namespace{Name: "ubuntu:" + database.UbuntuReleasesMapping[md["release"]]},
|
||||
Name: md["package"],
|
||||
},
|
||||
Version: version,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, version),
|
||||
}
|
||||
vulnerability.FixedIn = append(vulnerability.FixedIn, featureVersion)
|
||||
}
|
||||
|
@ -48,21 +48,21 @@ func TestUbuntuParser(t *testing.T) {
|
||||
Namespace: database.Namespace{Name: "ubuntu:14.04"},
|
||||
Name: "libmspack",
|
||||
},
|
||||
Version: types.MaxVersion,
|
||||
FixedInVersions: types.NewFixedInVersionsFromOV(types.OpGreaterEqual, types.MaxVersion),
|
||||
},
|
||||
{
|
||||
Feature: database.Feature{
|
||||
Namespace: database.Namespace{Name: "ubuntu:15.04"},
|
||||
Name: "libmspack",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("0.4-3"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 0.4-3"),
|
||||
},
|
||||
{
|
||||
Feature: database.Feature{
|
||||
Namespace: database.Namespace{Name: "ubuntu:15.10"},
|
||||
Name: "libmspack-anotherpkg",
|
||||
},
|
||||
Version: types.NewVersionUnsafe("0.1"),
|
||||
FixedInVersions: types.NewFixedInVersionsUnsafe(">= 0.1"),
|
||||
},
|
||||
}
|
||||
|
||||
|
237
utils/types/fixedin_versions.go
Normal file
237
utils/types/fixedin_versions.go
Normal file
@ -0,0 +1,237 @@
|
||||
// Copyright 2016 clair authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type Operator string
|
||||
|
||||
const (
|
||||
OpNotEqual Operator = "!="
|
||||
OpLessThan Operator = "<"
|
||||
OpLessEqual Operator = "<="
|
||||
OpEqualTo Operator = "=="
|
||||
OpGreaterEqual Operator = ">="
|
||||
OpGreaterThan Operator = ">"
|
||||
)
|
||||
|
||||
type FixedInVersions struct {
|
||||
fivs [][]operVersion
|
||||
}
|
||||
|
||||
type operVersion struct {
|
||||
oper Operator
|
||||
version Version
|
||||
}
|
||||
|
||||
type ovState string
|
||||
|
||||
const (
|
||||
ovStateInit ovState = "init"
|
||||
ovStateOper ovState = "operation"
|
||||
ovStateVersion ovState = "version"
|
||||
)
|
||||
|
||||
func isOperChar(ch rune) bool {
|
||||
return ch == '>' || ch == '<' || ch == '='
|
||||
}
|
||||
|
||||
func getOperator(str string) (oper Operator, error error) {
|
||||
switch str {
|
||||
case "!=":
|
||||
case "<":
|
||||
case "<=":
|
||||
case "==":
|
||||
case ">=":
|
||||
case ">":
|
||||
default:
|
||||
return oper, fmt.Errorf("Invalid operator: '%s'", str)
|
||||
}
|
||||
|
||||
return Operator(str), nil
|
||||
}
|
||||
|
||||
func getFixedinVersion(content string) (ovs []operVersion, err error) {
|
||||
state := ovStateInit
|
||||
begin := 0
|
||||
var ov operVersion
|
||||
for i, ch := range content {
|
||||
if unicode.IsSpace(ch) {
|
||||
continue
|
||||
}
|
||||
switch state {
|
||||
case ovStateInit:
|
||||
if isOperChar(ch) {
|
||||
state = ovStateOper
|
||||
} else {
|
||||
// Default to '>='
|
||||
ov.oper = OpGreaterEqual
|
||||
state = ovStateVersion
|
||||
}
|
||||
begin = i
|
||||
case ovStateOper:
|
||||
if !isOperChar(ch) {
|
||||
state = ovStateVersion
|
||||
if ov.oper, err = getOperator(strings.TrimSpace(content[begin:i])); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
begin = i
|
||||
}
|
||||
case ovStateVersion:
|
||||
if isOperChar(ch) {
|
||||
state = ovStateOper
|
||||
if ov.version, err = NewVersion(strings.TrimSpace(content[begin:i])); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ovs = append(ovs, ov)
|
||||
begin = i
|
||||
}
|
||||
}
|
||||
}
|
||||
if state == ovStateVersion {
|
||||
if ov.version, err = NewVersion(strings.TrimSpace(content[begin:len(content)])); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ovs = append(ovs, ov)
|
||||
}
|
||||
|
||||
if len(ovs) == 0 {
|
||||
err = fmt.Errorf("Failed to parse '%s'", content)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (ov operVersion) patched(version Version) bool {
|
||||
val := version.Compare(ov.version)
|
||||
switch ov.oper {
|
||||
case OpNotEqual:
|
||||
return val != 0
|
||||
case OpLessThan:
|
||||
return val < 0
|
||||
case OpLessEqual:
|
||||
return val <= 0
|
||||
case OpEqualTo:
|
||||
return val == 0
|
||||
case OpGreaterEqual:
|
||||
return val >= 0
|
||||
case OpGreaterThan:
|
||||
return val > 0
|
||||
}
|
||||
|
||||
//Cannot get here
|
||||
return false
|
||||
}
|
||||
|
||||
// String returns the string representation of a FixedInVersions
|
||||
func (fivs FixedInVersions) String() (s string) {
|
||||
firstFiv := false
|
||||
for _, fiv := range fivs.fivs {
|
||||
if !firstFiv {
|
||||
firstFiv = true
|
||||
} else {
|
||||
s += " || "
|
||||
}
|
||||
|
||||
firstOV := false
|
||||
for _, ov := range fiv {
|
||||
if !firstOV {
|
||||
firstOV = true
|
||||
} else {
|
||||
s += " "
|
||||
}
|
||||
s += string(ov.oper) + ov.version.String()
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (fivs FixedInVersions) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(fivs.String())
|
||||
}
|
||||
|
||||
func (fivs *FixedInVersions) UnmarshalJSON(b []byte) (err error) {
|
||||
var str string
|
||||
json.Unmarshal(b, &str)
|
||||
vp := NewFixedInVersionsUnsafe(str)
|
||||
*fivs = vp
|
||||
return
|
||||
}
|
||||
|
||||
func (fivs *FixedInVersions) Scan(value interface{}) (err error) {
|
||||
val, ok := value.([]byte)
|
||||
if !ok {
|
||||
return errors.New("could not scan a Version from a non-string input")
|
||||
}
|
||||
*fivs, err = NewFixedInVersions(string(val))
|
||||
return
|
||||
}
|
||||
|
||||
func (fivs *FixedInVersions) Value() (driver.Value, error) {
|
||||
return fivs.String(), nil
|
||||
}
|
||||
|
||||
func (fivs FixedInVersions) Affected(version Version) bool {
|
||||
for _, fiv := range fivs.fivs {
|
||||
affected := false
|
||||
for _, ov := range fiv {
|
||||
if !ov.patched(version) {
|
||||
affected = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !affected {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func NewFixedInVersionsFromOV(oper Operator, version Version) FixedInVersions {
|
||||
var fivs FixedInVersions
|
||||
var fiv []operVersion
|
||||
|
||||
fiv = append(fiv, operVersion{oper, version})
|
||||
fivs.fivs = append(fivs.fivs, fiv)
|
||||
|
||||
return fivs
|
||||
}
|
||||
|
||||
func NewFixedInVersions(str string) (FixedInVersions, error) {
|
||||
var fivs FixedInVersions
|
||||
for _, ovsStr := range strings.Split(str, "||") {
|
||||
if fiv, err := getFixedinVersion(ovsStr); err == nil {
|
||||
fivs.fivs = append(fivs.fivs, fiv)
|
||||
} else {
|
||||
return fivs, err
|
||||
}
|
||||
}
|
||||
|
||||
return fivs, nil
|
||||
}
|
||||
|
||||
func NewFixedInVersionsUnsafe(str string) FixedInVersions {
|
||||
fivs, _ := NewFixedInVersions(str)
|
||||
return fivs
|
||||
}
|
69
utils/types/fixedin_versions_test.go
Normal file
69
utils/types/fixedin_versions_test.go
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2016 clair authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFixedInVersions(t *testing.T) {
|
||||
invalid_version := "3.1.3 < 4.0.0 || >= "
|
||||
fivs, err := NewFixedInVersions(invalid_version)
|
||||
assert.Error(t, err, "Failed to parse '%s'", ">=")
|
||||
|
||||
invalid_version = "3.1.3 < ab.0.0 || >= "
|
||||
fivs, err = NewFixedInVersions(invalid_version)
|
||||
assert.Error(t, err, "Failed to parse '%s'", ">=")
|
||||
|
||||
valid_version := "3.1.3"
|
||||
fivs, err = NewFixedInVersions(valid_version)
|
||||
assert.Nil(t, err)
|
||||
|
||||
valid_version = ">=3.1.3 <4.0.0 || >=4.1.1"
|
||||
fivs, err = NewFixedInVersions(valid_version)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, strings.Replace(fivs.String(), " ", "", -1), strings.Replace(valid_version, " ", "", -1))
|
||||
|
||||
for _, fiv := range fivs.fivs {
|
||||
if len(fiv) == 1 {
|
||||
assert.Equal(t, OpGreaterEqual, fiv[0].oper)
|
||||
assert.Equal(t, NewVersionUnsafe("4.1.1"), fiv[0].version)
|
||||
} else {
|
||||
for _, ov := range fiv {
|
||||
if ov.oper == OpGreaterEqual {
|
||||
assert.Equal(t, NewVersionUnsafe("3.1.3"), ov.version)
|
||||
} else if ov.oper == OpLessThan {
|
||||
assert.Equal(t, NewVersionUnsafe("4.0.0"), ov.version)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
version string
|
||||
expected bool
|
||||
}{
|
||||
{"4.2", false},
|
||||
{"4.0.0", true},
|
||||
{"3.1.3", false},
|
||||
{"3.1.2", true},
|
||||
}
|
||||
for _, c := range cases {
|
||||
assert.Equal(t, fivs.Affected(NewVersionUnsafe(c.version)), c.expected)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user