From b92ca58d6911f4642a9caf0fa4c86e9c2e73fa69 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 16 May 2026 18:28:42 +0800 Subject: [PATCH] vim-patch:9.2.0490: matchfuzzy() can crash on long multi-word patterns (#39809) Problem: matchfuzzy() can crash on long multi-word patterns. Solution: Clamp pat_chars to maxMatches and stop before calling match_positions() when the buffer is full (glepnir). closes: vim/vim#20209 https://github.com/vim/vim/commit/88b00d1c57c8713ac5e7f2828c07e3c7da94ac79 Co-authored-by: glepnir --- src/nvim/fuzzy.c | 14 +++++++++++++- test/old/testdir/test_matchfuzzy.vim | 9 +++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/nvim/fuzzy.c b/src/nvim/fuzzy.c index 4d7f6a08e0..e9dd67e732 100644 --- a/src/nvim/fuzzy.c +++ b/src/nvim/fuzzy.c @@ -78,6 +78,7 @@ bool fuzzy_match(char *const str, const char *const pat_arg, const bool matchseq { bool complete = false; int numMatches = 0; + int pat_chars = 0; *outScore = 0; @@ -104,6 +105,17 @@ bool fuzzy_match(char *const str, const char *const pat_arg, const bool matchseq } *p = NUL; } + // match_positions() always writes pat_chars entries, + // so bail if they won't fit. + pat_chars = mb_charlen(pat); + if (pat_chars > maxMatches) { + pat_chars = maxMatches; + } + if (numMatches > maxMatches - pat_chars) { + numMatches = 0; + *outScore = FUZZY_SCORE_NONE; + break; + } int score = FUZZY_SCORE_NONE; if (has_match(pat, str)) { @@ -131,7 +143,7 @@ bool fuzzy_match(char *const str, const char *const pat_arg, const bool matchseq *outScore += score; } - numMatches += mb_charlen(pat); + numMatches += pat_chars; if (complete || numMatches >= maxMatches) { break; diff --git a/test/old/testdir/test_matchfuzzy.vim b/test/old/testdir/test_matchfuzzy.vim index 127087175f..76f664d691 100644 --- a/test/old/testdir/test_matchfuzzy.vim +++ b/test/old/testdir/test_matchfuzzy.vim @@ -333,4 +333,13 @@ func Test_matchfuzzy_initialized() call StopVimInTerminal(buf) endfunc +func Test_matchfuzzy_long_multiword_no_overflow() + let word = repeat('a', 100) + let pat_ok = repeat(word . ' ', 9) . word + call assert_equal([word], matchfuzzy([word], pat_ok)) + + let pat_overflow = repeat(word . ' ', 14) . word + call assert_equal([[], [], []], matchfuzzypos([word], pat_overflow)) +endfunc + " vim: shiftwidth=2 sts=2 expandtab