From afa2a81a88d123d4c39a75bddfc41559b81188b2 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Tue, 16 Sep 2025 19:19:42 +0000 Subject: [PATCH] patch 9.1.1766: Vim9: some functions do not handle null_string correctly Problem: Vim9: some Vim9 functions do not handle null_string correctly and may crash Vim (kennypete). Solution: Check for null_string correctly in the searchpair() and substitute() functions (Yegappan Lakshmanan). fixes: #18309 closes: #18311 Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- src/testdir/test_vim9_builtin.vim | 41 +++++++++++++++++++++++++++++++ src/version.c | 2 ++ src/vim9expr.c | 10 +++++--- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 8b84a47eca..1cf4010cd8 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -3875,6 +3875,26 @@ def Test_searchpair() errors = ['E1013: Argument 7: type mismatch, expected number but got string', 'E1210: Number required for argument 7'] v9.CheckSourceDefAndScriptFailure(['searchpair("a", "b", "c", "r", "1", 3, "g")'], errors) v9.CheckSourceDefAndScriptFailure(['searchpairpos("a", "b", "c", "r", "1", 3, "g")'], errors) + + # calling searchpair() with null_string arguments + lines =<< trim END + new + setline(1, ['{', '', '}']) + + cursor(1, 1) + searchpair('{', '', '}', '', null_string) + assert_equal(3, line('.')) + + cursor(1, 1) + searchpair('{', '', '}', null_string, null_string) + assert_equal(3, line('.')) + + cursor(1, 1) + searchpair(null_string, null_string, null_string, null_string, null_string) + assert_equal(1, line('.')) + bw! + END + v9.CheckSourceDefAndScriptSuccess(lines) enddef def Test_searchpos() @@ -4538,6 +4558,27 @@ def Test_substitute() assert_equal("4", substitute("3", '\d', '\="text" x', 'g')) END v9.CheckSourceDefAndScriptFailure(lines, 'E488: Trailing characters: x') + + # check for using null_string as argument to substitute() + lines =<< trim END + assert_equal('Vim', 'Vimp'->substitute('p', '', null_string)) + assert_equal('Vim', 'Vimp'->substitute('p', null_string, null_string)) + assert_equal('Vimp', 'Vimp'->substitute(null_string, null_string, null_string)) + assert_equal('', substitute(null_string, null_string, null_string, null_string)) + END + v9.CheckSourceDefAndScriptSuccess(lines) + + # lambda function calling substitute() with null_string arguments + lines =<< trim END + const Subst_Fn: func = (a: string, b: string, c: string, d: string): string => { + return a->substitute(b, c, d) + } + assert_equal('Vim', Subst_Fn('Vimp', 'p', '', null_string)) + assert_equal('Vim', Subst_Fn('Vimp', 'p', null_string, null_string)) + assert_equal('Vimp', Subst_Fn('Vimp', null_string, null_string, null_string)) + assert_equal('', Subst_Fn(null_string, null_string, null_string, null_string)) + END + v9.CheckSourceDefAndScriptSuccess(lines) enddef def Test_swapinfo() diff --git a/src/version.c b/src/version.c index f58befda00..8be4f5f848 100644 --- a/src/version.c +++ b/src/version.c @@ -724,6 +724,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1766, /**/ 1765, /**/ diff --git a/src/vim9expr.c b/src/vim9expr.c index f3aa4b1f5c..375986cb7e 100644 --- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -1199,7 +1199,9 @@ compile_arguments( isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count; // {skip} argument of searchpair() can be compiled if not empty - if (isn->isn_type == ISN_PUSHS && *isn->isn_arg.string != NUL) + if (isn->isn_type == ISN_PUSHS + && isn->isn_arg.string != NULL + && *isn->isn_arg.string != NUL) compile_string(isn, cctx, 0); } else if (special_fn == CA_SUBSTITUTE && *argcount == 3 @@ -1209,8 +1211,10 @@ compile_arguments( // {sub} argument of substitute() can be compiled if it starts // with \= - if (isn->isn_type == ISN_PUSHS && isn->isn_arg.string[0] == '\\' - && isn->isn_arg.string[1] == '=') + if (isn->isn_type == ISN_PUSHS + && isn->isn_arg.string != NULL + && isn->isn_arg.string[0] == '\\' + && isn->isn_arg.string[1] == '=') compile_string(isn, cctx, 2); }