Commit: patch 9.2.0209: freeze during wildmenu completion

3 views
Skip to first unread message

Christian Brabandt

unread,
Mar 19, 2026, 6:17:07 PM (4 days ago) Mar 19
to vim...@googlegroups.com
patch 9.2.0209: freeze during wildmenu completion

Commit: https://github.com/vim/vim/commit/332dd22ed48244d67524933453049c6c866bcabf
Author: Yasuhiro Matsumoto <matt...@gmail.com>
Date: Thu Mar 19 21:59:45 2026 +0000

patch 9.2.0209: freeze during wildmenu completion

Problem: Vim may freeze if setcmdline() is called while the wildmenu or
cmdline popup menu is active (rendcrx)
Solution: Cleanup completion state if cmdbuff_replaced flag has been set
(Yasuhiro Matsumoto)

fixes: #19742
closes: #19744

Co-authored-by: zeertzjq <zeer...@outlook.com>
Signed-off-by: Yasuhiro Matsumoto <matt...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/ex_getln.c b/src/ex_getln.c
index ce28088d5..917e67529 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -1899,6 +1899,21 @@ getcmdline_int(
c = safe_vgetc();
} while (c == K_IGNORE || c == K_NOP);

+ // If the cmdline was replaced externally (e.g. by setcmdline()
+ // during an <expr> mapping), clean up the wildmenu completion
+ // state to avoid using stale completion data.
+ if (ccline.cmdbuff_replaced && xpc.xp_numfiles > 0)
+ {
+ if (cmdline_pum_active())
+ cmdline_pum_remove(&ccline, FALSE);
+ (void)ExpandOne(&xpc, NULL, NULL, 0, WILD_FREE);
+ did_wild_list = FALSE;
+ xpc.xp_context = EXPAND_NOTHING;
+ wim_index = 0;
+ wildmenu_cleanup(&ccline);
+ }
+ ccline.cmdbuff_replaced = FALSE;
+
// Skip wildmenu during history navigation via Up/Down keys
if (c == K_WILD && did_hist_navigate)
{
@@ -4518,6 +4533,7 @@ set_cmdline_str(char_u *str, int pos)

p->cmdpos = pos < 0 || pos > p->cmdlen ? p->cmdlen : pos;
new_cmdpos = p->cmdpos;
+ p->cmdbuff_replaced = TRUE;

redrawcmd();

diff --git a/src/structs.h b/src/structs.h
index 2b8cb3db1..0e61aedef 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -716,6 +716,8 @@ typedef struct
char_u *xp_arg; // user-defined expansion arg
int input_fn; // when TRUE Invoked for input() function
#endif
+ int cmdbuff_replaced; // when TRUE cmdline was replaced externally
+ // (e.g. by setcmdline())
} cmdline_info_T;

/*
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 419d48723..2810e0b7e 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -4488,6 +4488,23 @@ func Test_setcmdline()
call feedkeys(":a\<CR>", 'tx')
call assert_equal('let foo=0', @:)
cunmap a
+
+ " setcmdline() during wildmenu completion should not freeze.
+ " Stripping completion state when cmdline was replaced externally.
+ set wildmenu
+ call mkdir('Xsetcmdlinedir', 'pR')
+ call writefile([], 'Xsetcmdlinedir/Xfile1')
+ call writefile([], 'Xsetcmdlinedir/Xfile2')
+ func g:SetCmdLineEmpty()
+ call setcmdline('', 1)
+ return "\<Left>"
+ endfunc
+ cnoremap <expr> a g:SetCmdLineEmpty()
+ call feedkeys(":e Xsetcmdlinedir/\<Tab>a\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"', @:)
+ cunmap a
+ delfunc g:SetCmdLineEmpty
+ set nowildmenu
endfunc

func Test_rulerformat_position()
diff --git a/src/version.c b/src/version.c
index bd95e9e3c..820096693 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 209,
/**/
208,
/**/
Reply all
Reply to author
Forward
0 new messages