Skip to content

Commit

Permalink
Merge pull request #253 from mattfarina/fix-bad-versions
Browse files Browse the repository at this point in the history
Fix for allowing some version that were invalid
  • Loading branch information
mattfarina authored Nov 19, 2024
2 parents e6e3d4d + 252dd61 commit 1558ca3
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 9 deletions.
24 changes: 15 additions & 9 deletions version.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ var (
)

// semVerRegex is the regular expression used to parse a semantic version.
const semVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` +
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
// This is not the official regex from the semver spec. It has been modified to allow for loose handling
// where versions like 2.1 are detected.
const semVerRegex string = `v?(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-]+)*))?`

// Version represents a single semantic version.
type Version struct {
Expand Down Expand Up @@ -146,8 +148,8 @@ func NewVersion(v string) (*Version, error) {
}

sv := &Version{
metadata: m[8],
pre: m[5],
metadata: m[5],
pre: m[4],
original: v,
}

Expand All @@ -158,7 +160,7 @@ func NewVersion(v string) (*Version, error) {
}

if m[2] != "" {
sv.minor, err = strconv.ParseUint(strings.TrimPrefix(m[2], "."), 10, 64)
sv.minor, err = strconv.ParseUint(m[2], 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
Expand All @@ -167,7 +169,7 @@ func NewVersion(v string) (*Version, error) {
}

if m[3] != "" {
sv.patch, err = strconv.ParseUint(strings.TrimPrefix(m[3], "."), 10, 64)
sv.patch, err = strconv.ParseUint(m[3], 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
Expand Down Expand Up @@ -612,7 +614,9 @@ func containsOnly(s string, comp string) bool {
func validatePrerelease(p string) error {
eparts := strings.Split(p, ".")
for _, p := range eparts {
if containsOnly(p, num) {
if p == "" {
return ErrInvalidMetadata
} else if containsOnly(p, num) {
if len(p) > 1 && p[0] == '0' {
return ErrSegmentStartsZero
}
Expand All @@ -631,7 +635,9 @@ func validatePrerelease(p string) error {
func validateMetadata(m string) error {
eparts := strings.Split(m, ".")
for _, p := range eparts {
if !containsOnly(p, allowed) {
if p == "" {
return ErrInvalidMetadata
} else if !containsOnly(p, allowed) {
return ErrInvalidMetadata
}
}
Expand Down
31 changes: 31 additions & 0 deletions version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func TestStrictNewVersion(t *testing.T) {
{"v1.0", true},
{"1", true},
{"v1", true},
{"1.2", true},
{"1.2.beta", true},
{"v1.2.beta", true},
{"foo", true},
Expand All @@ -45,6 +46,25 @@ func TestStrictNewVersion(t *testing.T) {
// The SemVer spec in a pre-release expects to allow [0-9A-Za-z-]. But,
// the lack of all 3 parts in this version should produce an error.
{"20221209-update-renovatejson-v4", true},

// Various cases that are invalid semver
{"1.1.2+.123", true}, // A leading . in build metadata. This would signify that the first segment is empty
{"1.0.0-alpha_beta", true}, // An underscore in the pre-release is an invalid character
{"1.0.0-alpha..", true}, // Multiple empty segments
{"1.0.0-alpha..1", true}, // Multiple empty segments but one with a value
{"01.1.1", true}, // A leading 0 on a number segment
{"1.01.1", true}, // A leading 0 on a number segment
{"1.1.01", true}, // A leading 0 on a number segment
{"9.8.7+meta+meta", true}, // Multiple metadata parts
{"1.2.31----RC-SNAPSHOT.12.09.1--.12+788", true}, // Leading 0 in a number part of a pre-release segment
{"1.2.3-0123", true},
{"1.2.3-0123.0123", true},
{"+invalid", true},
{"-invalid", true},
{"-invalid.01", true},
{"alpha+beta", true},
{"1.2.3-alpha_beta+foo", true},
{"1.0.0-alpha..1", true},
}

for _, tc := range tests {
Expand Down Expand Up @@ -101,6 +121,17 @@ func TestNewVersion(t *testing.T) {

// The SemVer spec in a pre-release expects to allow [0-9A-Za-z-].
{"20221209-update-renovatejson-v4", false},

// Various cases that are invalid semver
{"1.1.2+.123", true}, // A leading . in build metadata. This would signify that the first segment is empty
{"1.0.0-alpha_beta", true}, // An underscore in the pre-release is an invalid character
{"1.0.0-alpha..", true}, // Multiple empty segments
{"1.0.0-alpha..1", true}, // Multiple empty segments but one with a value
{"01.1.1", true}, // A leading 0 on a number segment
{"1.01.1", true}, // A leading 0 on a number segment
{"1.1.01", true}, // A leading 0 on a number segment
{"9.8.7+meta+meta", true}, // Multiple metadata parts
{"1.2.31----RC-SNAPSHOT.12.09.1--.12+788", true}, // Leading 0 in a number part of a pre-release segment
}

for _, tc := range tests {
Expand Down

0 comments on commit 1558ca3

Please sign in to comment.