Skip to content

is_valid() accepts versions that compare() cannot order (int_max_str_digits) #487

Closed

Description

@fitness-trener

Which version of Python is the problem with?

3.11 (and any version with the int_max_str_digits guard, i.e. 3.11+ and patched 3.7–3.10)

What semver version are you using?

3.1.0 (pure-Python parser; the optional native backend is not installed)

What OS are you using?

Windows

Situation

Version.is_valid() accepts a version whose pre-release has a numeric identifier longer than 4300 digits, but compare() cannot order that version — not even against itself — because _nat_cmp calls int() on the identifier and CPython's integer-string conversion limit raises ValueError.

So a caller that validates untrusted version strings with is_valid and then sorts them gets an unexpected ValueError instead of an ordering.

A closely related case: a major/minor/patch part longer than 4300 digits is valid per SemVer 2.0.0 (the BNF has no length bound), but is_valid returns False because the same ValueError is swallowed. That one is arguably fine given the spec FAQ's "use good judgment" note on size — I mention it only because it is the other side of the same limit.

How to reproduce

import semver

s = "0.0.0-" + "1" * 4301
assert semver.Version.is_valid(s)          # True
semver.Version.parse(s).compare(s)         # ValueError: Exceeds the limit (4300 digits) for integer string conversion
semver.compare(s, "0.0.0-2")               # same ValueError

semver.Version.is_valid("1" * 4301 + ".0.0")   # False (the core part hits the same limit)

Expected behavior

is_valid and compare agree: either a version that is_valid accepts can be compared, or is_valid rejects it.

One way that avoids the limit entirely (and any int() work in comparisons): for two numeric identifiers without leading zeros, compare (len(a), a) < (len(b), b) — longer means larger, equal length compares lexicographically — which is exactly numeric order for canonical digit strings (SemVer §11.4.1). The core parts could use the same rule.

Environment

CPython 3.11.15, sys.get_int_max_str_digits() == 4300.

This was found by differential-testing semver 3.1.0 against an independent implementation of SemVer 2.0.0 (60,000 validity checks and 220,000 comparisons); apart from this digit limit, the two agreed on every input.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    SIze

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions