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