From: Yasuhiro Matsumoto Date: Thu, 19 Mar 2026 21:59:45 +0000 (+0000) Subject: patch 9.2.0209: freeze during wildmenu completion X-Git-Tag: v9.2.0209^0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=332dd22ed48244d67524933453049c6c866bcabf;p=thirdparty%2Fvim.git 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 Signed-off-by: Yasuhiro Matsumoto Signed-off-by: Christian Brabandt --- diff --git a/src/ex_getln.c b/src/ex_getln.c index ce28088d56..917e67529b 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 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 2b8cb3db1f..0e61aedef4 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 419d487233..2810e0b7e8 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -4488,6 +4488,23 @@ func Test_setcmdline() call feedkeys(":a\", '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 "\" + endfunc + cnoremap a g:SetCmdLineEmpty() + call feedkeys(":e Xsetcmdlinedir/\a\\"\", '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 bd95e9e3c4..8200966934 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, /**/