Skip to content

Commit

Permalink
feat: support SEMVER ranges (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Rath authored Mar 11, 2022
1 parent 4b2d304 commit 4abfc49
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 9 deletions.
18 changes: 9 additions & 9 deletions detector/database/osv.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ type AffectsRange struct {
Events []RangeEvent `json:"events"`
}

func (ar AffectsRange) containsEcosystem(v string) bool {
if ar.Type != TypeEcosystem {
func (ar AffectsRange) containsVersion(v string) bool {
if ar.Type != TypeEcosystem && ar.Type != TypeSemver {
return false
}
// todo: we should probably warn here
Expand All @@ -80,14 +80,14 @@ func (ar AffectsRange) containsEcosystem(v string) bool {

type Affects []AffectsRange

// AffectsEcosystem checks if the given version is within the range
// specified by the events of any "Ecosystem" type ranges
func (a Affects) AffectsEcosystem(v string) bool {
// affectsVersion checks if the given version is within the range
// specified by the events of any "Ecosystem" or "Semver" type ranges
func (a Affects) affectsVersion(v string) bool {
for _, r := range a {
if r.Type != TypeEcosystem {
continue
if r.Type != TypeEcosystem && r.Type != TypeSemver {
return false
}
if r.containsEcosystem(v) {
if r.containsVersion(v) {
return true
}
}
Expand Down Expand Up @@ -156,7 +156,7 @@ func (osv *OSV) IsAffected(pkg detector.PackageDetails) bool {
continue
}

if affected.Ranges.AffectsEcosystem(pkg.Version) {
if affected.Ranges.affectsVersion(pkg.Version) {
return true
}
}
Expand Down
134 changes: 134 additions & 0 deletions detector/database/osv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ func buildEcosystemAffectsRange(events ...database.RangeEvent) database.AffectsR
return database.AffectsRange{Type: database.TypeEcosystem, Events: events}
}

func buildSemverAffectsRange(events ...database.RangeEvent) database.AffectsRange {
return database.AffectsRange{Type: database.TypeSemver, Events: events}
}

func TestPackage_NormalizedName(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -338,3 +342,133 @@ func TestOSV_IsAffected_AffectsWithEcosystem_PipNamesAreNormalised(t *testing.T)
t.Errorf("Expected OSV not to normalize names of non-pip packages, but it did")
}
}

func TestOSV_IsAffected_AffectsWithSemver_DifferentEcosystem(t *testing.T) {
t.Parallel()

osv := buildOSVWithAffected(
database.Affected{
Package: database.Package{Ecosystem: parsers.PipEcosystem, Name: "my-package"},
Ranges: []database.AffectsRange{
buildSemverAffectsRange(database.RangeEvent{Introduced: "0"}),
},
},
)

for _, v := range []string{"1.0.0", "1.1.1", "2.0.0"} {
expectIsAffected(t, osv, v, false)
}
}

func TestOSV_IsAffected_AffectsWithSemver_SingleAffected(t *testing.T) {
t.Parallel()

var osv database.OSV

// "Introduced: 0" means everything is affected
osv = buildOSVWithAffected(
database.Affected{
Package: database.Package{Ecosystem: parsers.NpmEcosystem, Name: "my-package"},
Ranges: []database.AffectsRange{
buildSemverAffectsRange(database.RangeEvent{Introduced: "0"}),
},
},
)

for _, v := range []string{"v1.0.0", "v1.1.1", "v2.0.0"} {
expectIsAffected(t, osv, v, true)
}

// "Fixed: 1" means all versions after this are not vulnerable
osv = buildOSVWithAffected(
database.Affected{
Package: database.Package{Ecosystem: parsers.NpmEcosystem, Name: "my-package"},
Ranges: []database.AffectsRange{
buildSemverAffectsRange(
database.RangeEvent{Introduced: "0"},
database.RangeEvent{Fixed: "1.0.0"},
),
},
},
)

for _, v := range []string{"0.0.0", "0.1.0", "0.0.0.1", "1.0.0-rc"} {
expectIsAffected(t, osv, v, true)
}

for _, v := range []string{"1.0.0", "1.1.0", "2.0.0"} {
expectIsAffected(t, osv, v, false)
}

// multiple fixes and introduced
osv = buildOSVWithAffected(
database.Affected{
Package: database.Package{Ecosystem: parsers.NpmEcosystem, Name: "my-package"},
Ranges: []database.AffectsRange{
buildSemverAffectsRange(
database.RangeEvent{Introduced: "0"},
database.RangeEvent{Fixed: "1"},
database.RangeEvent{Introduced: "2.1.0"},
database.RangeEvent{Fixed: "3.2.0"},
),
},
},
)

for _, v := range []string{"0.0.0", "0.1.0", "0.0.0.1", "1.0.0-rc"} {
expectIsAffected(t, osv, v, true)
}

for _, v := range []string{"1.0.0", "1.1.0", "2.0.0rc2", "2.0.1"} {
expectIsAffected(t, osv, v, false)
}

for _, v := range []string{"2.1.1", "2.3.4", "3.0.0", "3.0.0-rc"} {
expectIsAffected(t, osv, v, true)
}

for _, v := range []string{"3.2.0", "3.2.1", "4.0.0"} {
expectIsAffected(t, osv, v, false)
}
}

func TestOSV_IsAffected_AffectsWithSemver_MultipleAffected(t *testing.T) {
t.Parallel()

osv := buildOSVWithAffected(
database.Affected{
Package: database.Package{Ecosystem: parsers.NpmEcosystem, Name: "my-package"},
Ranges: []database.AffectsRange{
buildSemverAffectsRange(
database.RangeEvent{Introduced: "0"},
database.RangeEvent{Fixed: "1"},
),
},
},
database.Affected{
Package: database.Package{Ecosystem: parsers.NpmEcosystem, Name: "my-package"},
Ranges: []database.AffectsRange{
buildSemverAffectsRange(
database.RangeEvent{Introduced: "2.1.0"},
database.RangeEvent{Fixed: "3.2.0"},
),
},
},
)

for _, v := range []string{"0.0.0", "0.1.0", "0.0.0.1", "1.0.0-rc"} {
expectIsAffected(t, osv, v, true)
}

for _, v := range []string{"1.0.0", "1.1.0", "2.0.0rc2", "2.0.1"} {
expectIsAffected(t, osv, v, false)
}

for _, v := range []string{"2.1.1", "2.3.4", "3.0.0", "3.0.0-rc"} {
expectIsAffected(t, osv, v, true)
}

for _, v := range []string{"3.2.0", "3.2.1", "4.0.0"} {
expectIsAffected(t, osv, v, false)
}
}

0 comments on commit 4abfc49

Please sign in to comment.