Skip to content

Commit

Permalink
Fix scanning of a pre-release starting with 0
Browse files Browse the repository at this point in the history
A pre-release "Numeric identifiers MUST NOT include leading zeroes,"
according to SemVer 2.0. The existing code had accounted for this
limitation: when it found a pre-release starting with a 0 followed by a
digit, it would scan ahead and allow the value if it found an alphabetic
character. There were two bugs in the Implementation.

First, in addition to alphabetic characters, SemVer allows dashes. The
[project regex] matches `[a-zA-Z-]`. So add a check for a dash in
addition to `isalpha()`. Thanks to Dylan Bourque for the pull request
(#70).

The other bug was that the scanning was was not starting from the
character after the zero and following digit. It was, instead, starting
from that position subtracted from the length.

For example, if the pre-release started at character 7 and the semver
was 12 characters long, it would start scanning at character 13, well
*after* the start of the pre-release. If the pre-release started at
character 8 and the semver was 12 characters long, it would start
scanning from character 4, well *before* the start of the pre-release.

It's a wonder no errors were previously discovered.

Fix it by starting from the current character, and include some details
in Changes to help find existing bad values.
  • Loading branch information
theory committed Jul 20, 2024
1 parent 804f954 commit 02af21f
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 49 deletions.
10 changes: 10 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ Revision history for PostgreSQL extension semver.
- Changed the tests to use `CREATE EXTENSION` instead of loading the
SQL source file directory. The latter was required for Postgres 9.0
and lower, which have not been supported since v0.20.0 back in 2018.
- Fixed a bug that rejected pre-releases starting with a zero but
eventually include a dash, e.g., `1.2.3-02-3`. Thanks to Dylan
Bourque for the pull request (#70)!
- ***** WARNING: This release breaks compatibility with previous versions! ******
Fixed a bug in the scanning of pre-releases that start with a zero.
It now properly scans the rest of the pre-release string. As a result,
existing semvers with pre-releases the start with a zero may have been
incorrectly interpreted as valid. See the v0.30.0 changes below for
instructions for finding such invalid semvers. Discovered while
debugging unexpected test failures in #70.

0.32.1 2023-08-01T23:20:31Z
- Fixed compilation issue on Postgres 16.
Expand Down
9 changes: 5 additions & 4 deletions src/semver.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* + Sam Vilain <sam@vilain.net>
* + Tom Davis <tom@recursivedream.com>
* + Xavier Caron <xcaron@gmail.com>
* + David Wheeler <david@justatheory.com>
*
* Copyright 2010-2024 The pg-semver Maintainers. This program is Free
* Software; see the LICENSE file for the license conditions.
Expand Down Expand Up @@ -212,14 +213,14 @@ semver* parse_semver(char* str, bool lax, bool throw, bool* bad) {
if ((started_prerel || started_meta) && !skip_char) {
if (i >= 1 && (i == 1 || patch[i-2] == '.') && patch[i-1] == '0' && isdigit(next)) {
pred = true;
// Scan ahead.
for (p = len - atchar; p < len; p++) {
// Numeric identifiers must not include a leading 0. Scan ahead.
for (p = atchar; p < len; p++) {
if (str[p] == '.') {
// We got to the end of this bit.
break;
}
if (isalpha(str[p])) {
// If there is a letter, it's okay to start with a leading 0.
if (isalpha(str[p]) || str[p] == '-') {
// If there is a letter or a dash, it's okay to start with a leading 0.
pred = false;
break;
}
Expand Down
91 changes: 48 additions & 43 deletions test/expected/corpus.out
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
\set ECHO none
1..71
1..76
ok 1 - "0.0.4" is a valid semver
ok 2 - "1.2.3" is a valid semver
ok 3 - "10.20.30" is a valid semver
Expand Down Expand Up @@ -30,46 +30,51 @@ ok 27 - "1.2.3----R-S.12.9.1--.12+meta" is a valid semver
ok 28 - "1.2.3----RC-SNAPSHOT.12.9.1--.12" is a valid semver
ok 29 - "1.0.0+0.build.1-rc.10000aaa-kk-0.1" is a valid semver
ok 30 - "1.0.0-0A.is.legal" is a valid semver
not ok 31 - "99999999999999999999999.999999999999999999.99999999999999999" is a valid semver # TODO Large versions overflow integer bounds
# Failed (TODO) test 31: ""99999999999999999999999.999999999999999999.99999999999999999" is a valid semver"
ok 31 - "1.0.0-0010-1234" is a valid semver
ok 32 - "1.0.0-1.2.3-1234" is a valid semver
ok 33 - "1.0.0-1234" is a valid semver
ok 34 - "1.0.0-4321" is a valid semver
ok 35 - "0.0.0-00010101000000-000000000000" is a valid semver
not ok 36 - "99999999999999999999999.999999999999999999.99999999999999999" is a valid semver # TODO Large versions overflow integer bounds
# Failed (TODO) test 36: ""99999999999999999999999.999999999999999999.99999999999999999" is a valid semver"
# died: XX000: bad semver value '99999999999999999999999.999999999999999999.99999999999999999': version number exceeds 31-bit range
ok 32 - "1" is not a valid semver
ok 33 - "1.2" is not a valid semver
ok 34 - "1.2.3-0123" is not a valid semver
ok 35 - "1.2.3-0123.0123" is not a valid semver
ok 36 - "1.1.2+.123" is not a valid semver
ok 37 - "+invalid" is not a valid semver
ok 38 - "-invalid" is not a valid semver
ok 39 - "-invalid+invalid" is not a valid semver
ok 40 - "-invalid.01" is not a valid semver
ok 41 - "alpha" is not a valid semver
ok 42 - "alpha.beta" is not a valid semver
ok 43 - "alpha.beta.1" is not a valid semver
ok 44 - "alpha.1" is not a valid semver
ok 45 - "alpha+beta" is not a valid semver
ok 46 - "alpha_beta" is not a valid semver
ok 47 - "alpha." is not a valid semver
ok 48 - "alpha.." is not a valid semver
ok 49 - "beta" is not a valid semver
ok 50 - "1.0.0-alpha_beta" is not a valid semver
ok 51 - "-alpha." is not a valid semver
ok 52 - "1.0.0-alpha.." is not a valid semver
ok 53 - "1.0.0-alpha..1" is not a valid semver
ok 54 - "1.0.0-alpha...1" is not a valid semver
ok 55 - "1.0.0-alpha....1" is not a valid semver
ok 56 - "1.0.0-alpha.....1" is not a valid semver
ok 57 - "1.0.0-alpha......1" is not a valid semver
ok 58 - "1.0.0-alpha.......1" is not a valid semver
ok 59 - "01.1.1" is not a valid semver
ok 60 - "1.01.1" is not a valid semver
ok 61 - "1.1.01" is not a valid semver
ok 62 - "1.2" is not a valid semver
ok 63 - "1.2.3.DEV" is not a valid semver
ok 64 - "1.2-SNAPSHOT" is not a valid semver
ok 65 - "1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788" is not a valid semver
ok 66 - "1.2-RC-SNAPSHOT" is not a valid semver
ok 67 - "-1.0.3-gamma+b7718" is not a valid semver
ok 68 - "+justmeta" is not a valid semver
ok 69 - "9.8.7+meta+meta" is not a valid semver
ok 70 - "9.8.7-whatever+meta+meta" is not a valid semver
ok 71 - "99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12" is not a valid semver
ok 37 - "1" is not a valid semver
ok 38 - "1.2" is not a valid semver
ok 39 - "1.2.3-0123" is not a valid semver
ok 40 - "1.2.3-0123.0123" is not a valid semver
ok 41 - "1.1.2+.123" is not a valid semver
ok 42 - "+invalid" is not a valid semver
ok 43 - "-invalid" is not a valid semver
ok 44 - "-invalid+invalid" is not a valid semver
ok 45 - "-invalid.01" is not a valid semver
ok 46 - "alpha" is not a valid semver
ok 47 - "alpha.beta" is not a valid semver
ok 48 - "alpha.beta.1" is not a valid semver
ok 49 - "alpha.1" is not a valid semver
ok 50 - "alpha+beta" is not a valid semver
ok 51 - "alpha_beta" is not a valid semver
ok 52 - "alpha." is not a valid semver
ok 53 - "alpha.." is not a valid semver
ok 54 - "beta" is not a valid semver
ok 55 - "1.0.0-alpha_beta" is not a valid semver
ok 56 - "-alpha." is not a valid semver
ok 57 - "1.0.0-alpha.." is not a valid semver
ok 58 - "1.0.0-alpha..1" is not a valid semver
ok 59 - "1.0.0-alpha...1" is not a valid semver
ok 60 - "1.0.0-alpha....1" is not a valid semver
ok 61 - "1.0.0-alpha.....1" is not a valid semver
ok 62 - "1.0.0-alpha......1" is not a valid semver
ok 63 - "1.0.0-alpha.......1" is not a valid semver
ok 64 - "01.1.1" is not a valid semver
ok 65 - "1.01.1" is not a valid semver
ok 66 - "1.1.01" is not a valid semver
ok 67 - "1.2" is not a valid semver
ok 68 - "1.2.3.DEV" is not a valid semver
ok 69 - "1.2-SNAPSHOT" is not a valid semver
ok 70 - "1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788" is not a valid semver
ok 71 - "1.2-RC-SNAPSHOT" is not a valid semver
ok 72 - "-1.0.3-gamma+b7718" is not a valid semver
ok 73 - "+justmeta" is not a valid semver
ok 74 - "9.8.7+meta+meta" is not a valid semver
ok 75 - "9.8.7-whatever+meta+meta" is not a valid semver
ok 76 - "99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12" is not a valid semver
9 changes: 7 additions & 2 deletions test/sql/corpus.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ BEGIN;
\i test/pgtap-core.sql
CREATE EXTENSION semver;

SELECT plan(71);
SELECT plan(76);
--SELECT * FROM no_plan();

-- Valid Semantic Versions
Expand Down Expand Up @@ -43,7 +43,12 @@ SELECT lives_ok(
'1.2.3----R-S.12.9.1--.12+meta',
'1.2.3----RC-SNAPSHOT.12.9.1--.12',
'1.0.0+0.build.1-rc.10000aaa-kk-0.1',
'1.0.0-0A.is.legal'
'1.0.0-0A.is.legal',
'1.0.0-0010-1234',
'1.0.0-1.2.3-1234',
'1.0.0-1234',
'1.0.0-4321',
'0.0.0-00010101000000-000000000000'
--
]) AS v;

Expand Down

0 comments on commit 02af21f

Please sign in to comment.