commit d4a8d169a297bfe7aefb80b040062449a3152eaa
parent 0d3ee26860923e4be9f0a969b472a6ffaef4c83a
Author: Jan Edmund Lazo <jan.lazo@mail.utoronto.ca>
Date: Sat, 29 Nov 2025 10:34:24 -0500
vim-patch:9.0.0113: has() is not strict about parsing the patch version
Problem: has() is not strict about parsing the patch version.
Solution: Check the version more strictly. (Ken Takata, closes vim/vim#10752)
https://github.com/vim/vim/commit/d90f91fe3075bb51668ed926182b2163da9df001
Co-authored-by: K.Takata <kentkt@csc.jp>
Diffstat:
2 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
@@ -2801,18 +2801,23 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
} else if (STRNICMP(name, "patch", 5) == 0) {
if (name[5] == '-'
&& strlen(name) >= 11
- && ascii_isdigit(name[6])
- && ascii_isdigit(name[8])
- && ascii_isdigit(name[10])) {
- int major = atoi(name + 6);
- int minor = atoi(name + 8);
-
- // Expect "patch-9.9.01234".
- n = (major < VIM_VERSION_MAJOR
- || (major == VIM_VERSION_MAJOR
- && (minor < VIM_VERSION_MINOR
- || (minor == VIM_VERSION_MINOR
- && has_vim_patch(atoi(name + 10))))));
+ && (name[6] >= '1' && name[6] <= '9')) {
+ char *end;
+
+ // This works for patch-8.1.2, patch-9.0.3, patch-10.0.4, etc.
+ // Not for patch-9.10.5.
+ int major = (int)strtoul(name + 6, &end, 10);
+ if (*end == '.' && ascii_isdigit(end[1])
+ && end[2] == '.' && ascii_isdigit(end[3])) {
+ int minor = atoi(end + 1);
+
+ // Expect "patch-9.9.01234".
+ n = (major < VIM_VERSION_MAJOR
+ || (major == VIM_VERSION_MAJOR
+ && (minor < VIM_VERSION_MINOR
+ || (minor == VIM_VERSION_MINOR
+ && has_vim_patch(atoi(end + 3))))));
+ }
} else if (ascii_isdigit(name[5])) {
n = has_vim_patch(atoi(name + 5));
}
diff --git a/test/old/testdir/test_expr.vim b/test/old/testdir/test_expr.vim
@@ -37,13 +37,22 @@ func Test_version()
call assert_true(has('patch-6.9.999'))
call assert_true(has('patch-7.1.999'))
call assert_true(has('patch-7.4.123'))
+ call assert_true(has('patch-7.4.123 ')) " Traling space can be allowed.
call assert_false(has('patch-7'))
call assert_false(has('patch-7.4'))
call assert_false(has('patch-7.4.'))
call assert_false(has('patch-9.1.0'))
call assert_false(has('patch-9.9.1'))
+
call assert_false(has('patch-abc'))
+ call assert_false(has('patchabc'))
+
+ call assert_false(has('patch-8x001'))
+ call assert_false(has('patch-9X0X0'))
+ call assert_false(has('patch-9-0-0'))
+ call assert_false(has('patch-09.0.0'))
+ call assert_false(has('patch-9.00.0'))
endfunc
func Test_op_ternary()