diff --git a/NEWS.rst b/NEWS.rst index 5601b8078..a15d75bd5 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -255,6 +255,8 @@ Modules 5.7.0 (not yet released) shell meta-characters. Completion candidates were passed to ``compgen -W`` which evaluates command substitution syntax. (fix `CVE-2026-85013`_ found by AISLE in partnership with Red Hat) +* Accept abbreviated upper bounds in version ranges such as ``@3.20:3`` to + select versions starting at ``3.20`` within major version ``3``. .. _CVE-2026-85013: https://github.com/envmodules/modules/security/advisories/GHSA-8hrw-p88g-qhmg diff --git a/doc/source/design/advanced-module-version-specifiers.rst b/doc/source/design/advanced-module-version-specifiers.rst index 7828fdcc1..7b14b5dd1 100644 --- a/doc/source/design/advanced-module-version-specifiers.rst +++ b/doc/source/design/advanced-module-version-specifiers.rst @@ -91,6 +91,14 @@ Specification - for instance *@1:1.10* will matches *1.0* and *1.8* but not *1.12* + - the upper bound may be less precise than the lower bound + + - an abbreviated upper bound includes all versions that extend it, + provided they also satisfy the lower bound + - for instance *@1.2:1* matches *1.2* and *1.10* but not *1.1* or *2.0* + - a reversed range remains invalid unless the lower bound extends the + abbreviated upper bound, so *@2.0:1* is still rejected + - version could be specified as list - soft@vers,vers,vers diff --git a/doc/source/module.rst b/doc/source/module.rst index b9ab6e5ed..e0f58d3e6 100644 --- a/doc/source/module.rst +++ b/doc/source/module.rst @@ -3235,6 +3235,9 @@ the activation of the extended default mechanism (see to refer to more precise version numbers like ``1.2.3``. Characters ``.`` and ``-`` are considered version number separator to determine abbreviated versions. Range of versions on its side natively handles abbreviated versions. +The upper bound may be less precise than the lower bound. An abbreviated +upper bound includes all versions that extend it, provided they also satisfy +the lower bound. In order to be specified in a range of versions or compared to a range of versions, the version major element should corresponds to a number. For diff --git a/doc/source/modulefile.rst b/doc/source/modulefile.rst index 49194f469..cf34ef69d 100644 --- a/doc/source/modulefile.rst +++ b/doc/source/modulefile.rst @@ -2137,6 +2137,9 @@ notation like ``@1`` to refer to more precise version numbers like ``1.2.3``. Characters ``.`` and ``-`` are considered version number separator to determine abbreviated versions. Range of versions on its side natively handles abbreviated versions. +The upper bound may be less precise than the lower bound. An abbreviated +upper bound includes all versions that extend it, provided they also satisfy +the lower bound. In order to be specified in a range of versions or compared to a range of versions, the version major element should corresponds to a number. For diff --git a/tcl/modspec.tcl b/tcl/modspec.tcl index 97bf7e488..a614a449c 100644 --- a/tcl/modspec.tcl +++ b/tcl/modspec.tcl @@ -1246,7 +1246,9 @@ proc parseModuleVersionSpecifier {modspec} { set cmpspec le set versspec $hivers # between or equal - } elseif {[versioncmp $lovers $hivers] == 1} { + # An abbreviated upper bound includes its more precise versions. + } elseif {[versioncmp $lovers $hivers] == 1 && ![string match\ + $hivers[extendedDefaultCharGlobMatch] $lovers]} { set invalidversrange 1 } else { set cmpspec be diff --git a/testsuite/modules.70-maint/272-adv_version_spec-range.exp b/testsuite/modules.70-maint/272-adv_version_spec-range.exp index 0e4ac79de..6af813afb 100644 --- a/testsuite/modules.70-maint/272-adv_version_spec-range.exp +++ b/testsuite/modules.70-maint/272-adv_version_spec-range.exp @@ -84,6 +84,8 @@ testouterr_cmd sh {load mod@1::} ERR "$err_specvers'1::'" testouterr_cmd sh {load mod@1,:,} ERR "$err_specvers'1,:,'" testouterr_cmd sh {load mod@,:} ERR "$err_specvers',:'" testouterr_cmd sh {load mod@1.3:1.2} ERR "$err_rangevers'1.3:1.2'" +testouterr_cmd sh {load mod@4.1:3} ERR "$err_rangevers'4.1:3'" +testouterr_cmd sh {load mod@1.30:1.3} ERR "$err_rangevers'1.30:1.3'" testouterr_cmd sh {load mod@,<} ERR "$err_specvers',<'" testouterr_cmd sh {load mod@:<} ERR "$err_rangevers':<'" testouterr_cmd sh {load mod@1/1:2} ERR "$err_specvers'1/1:2'" @@ -113,6 +115,7 @@ testouterr_cmd sh {load extdfl @1.2:} $ans {} testouterr_cmd sh {load extdfl @:1.3.1} $ans {} testouterr_cmd sh {load extdfl @:1.3.7} $ans {} testouterr_cmd sh {load extdfl @1.2:1.3} $ans {} +testouterr_cmd sh {load extdfl @1.2:1} $ans {} testouterr_cmd sh {load extdfl @1.2.3:1.3.7} $ans {} testouterr_cmd sh {load extdfl @:2.0.1} $ans {} testouterr_cmd sh {load extdfl @:2.0} $ans {} @@ -162,6 +165,7 @@ testouterr_cmd sh {path extdfl/ @1.2:1.3} [list [list text $mp/extdfl/1.3.1]] {} # test all sub-cmd concerned by context testouterr_cmd sh {avail -t extdfl @1.3:1.4} OK "$mp:\nextdfl/1.3.1(default)\nextdfl/1.3.7\nextdfl/1.4.5" +testouterr_cmd sh {avail -t extdfl @1.3.7:1} OK "$mp:\nextdfl/1.3.7\nextdfl/1.4.5" testouterr_cmd_re sh {whatis extdfl@1.3.7:1.4.5} OK "$modlin $mpre $modlin \\s+extdfl/1.3.7: extdfl/1.3.7 \\s+extdfl/1.4.5: extdfl/1.4.5" @@ -187,6 +191,18 @@ testouterr_cmd sh {spider -t ext?fl @1.3:} OK "$mp:\nextdfl/1.3.1(default)\nextd testouterr_cmd sh {avail -t e??.* @:1.4} OK "$mp:\ne.t.fl/1.3.1\ne.t.fl/1.3.7\ne.t.fl/1.4.5" # additional version tests +# Abbreviated upper bounds apply independently of extended defaults. +foreach extdfl {0 1} { + setenv_var MODULES_EXTENDED_DEFAULT $extdfl + set ans [list [list text $mp/extdfl/1.3.7] [list text $mp/extdfl/1.4.5]] + testouterr_cmd sh {paths extdfl@1.3.7:1} $ans {} + testouterr_cmd sh {paths -i EXTDFL@1.3.7:1} $ans {} + set ans [list [list text $mp/extdfl/1.3.7]] + testouterr_cmd sh {paths extdfl@1.3.7:1.3} $ans {} + testouterr_cmd sh {paths extdfl@1.3.7:1.3,9:10} $ans {} +} +unsetenv_var MODULES_EXTENDED_DEFAULT + testouterr_cmd sh {avail -t extdfl8 @1.33:} OK "$mp:\nextdfl8/1.33" testouterr_cmd sh {avail -t extdfl8 @:1.3} OK "$mp:\nextdfl8/1.3.1\nextdfl8/1.3.7" testouterr_cmd sh {spider -t extdfl8 @:1.3} OK "$mp:\nextdfl8/1.3.1\nextdfl8/1.3.7" @@ -297,6 +313,7 @@ set ans [list] lappend ans [list set _LMFILES_ $mp/extdfl2/3.1.7] lappend ans [list set LOADEDMODULES extdfl2/3.1.7] testouterr_cmd sh {load extdfl2@3.0.2:3.1.7} $ans {} +testouterr_cmd sh {load extdfl2@3.1.7:3.1} $ans {} testouterr_cmd sh {load extdfl2@:3.1.7} $ans {} testouterr_cmd sh {load extdfl2@:3.1.7} $ans {} testouterr_cmd sh "load $mp/extdfl2 @:3.1.7" ERR "$err_file'$mp/extdfl2 @:3.1.7'"