patch 9.2.0647: matchfuzzypos() false exact match for long equal-length candidates
Commit: https://github.com/vim/vim/commit/1437f478158e71effdbcec3df5caa95af9b9a50a Author: glepnir <[email protected]> Date: Sun Jun 14 15:53:39 2026 +0000 patch 9.2.0647: matchfuzzypos() false exact match for long equal-length candidates Problem: When a candidate gets truncated to MATCH_MAX_LEN and ends up the same length as the needle, the n == m shortcut would return SCORE_MAX with positions 0..n-1, even if the strings actually differ. Solution: Only use the shortcut if the truncated strings are truly equal. Otherwise, fall back to regular matching. Example: echo matchfuzzypos(['x' .. repeat('a',1024)], repeat('a',1024)) closes: #20475 Signed-off-by: glepnir <[email protected]> Signed-off-by: Christian Brabandt <[email protected]> diff --git a/src/fuzzy.c b/src/fuzzy.c index fddfeb450..db006be0f 100644 --- a/src/fuzzy.c +++ b/src/fuzzy.c @@ -1144,12 +1144,26 @@ match_positions(char_u *needle, char_u *haystack, int_u *positions) // Since this method can only be called with a haystack which // matches needle. If the lengths of the strings are equal the // strings themselves must also be equal (ignoring case). - if (positions) + // After truncation to MATCH_MAX_LEN n == m can also happen for + // unequal strings, so check before taking the shortcut. + bool equal = true; + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - positions[i] = i; + if (match.lower_needle[i] != match.lower_haystack[i]) + { + equal = false; + break; + } + } + if (equal) + { + if (positions) + { + for (int i = 0; i < n; i++) + positions[i] = i; + } + return SCORE_MAX; } - return SCORE_MAX; } // ensure n * MATCH_MAX_LEN * 2 won't overflow diff --git a/src/testdir/test_matchfuzzy.vim b/src/testdir/test_matchfuzzy.vim index 8e1c2f882..f6565c754 100644 --- a/src/testdir/test_matchfuzzy.vim +++ b/src/testdir/test_matchfuzzy.vim @@ -331,7 +331,7 @@ func Test_matchfuzzy_long_multiword_no_overflow() call assert_equal([[], [], []], matchfuzzypos([word], pat_overflow)) endfunc -func Test_matchfuzzy_long_candidate() +func Test_matchfuzzy_oversized_candidate() let str = repeat('a', 1024) .. 'z' call assert_equal([], matchfuzzy([str], 'az')) call assert_equal([[], [], []], matchfuzzypos([str], 'az')) @@ -346,6 +346,10 @@ func Test_matchfuzzy_long_candidate() let e = matchfuzzypos([edge], 'aa') call assert_equal([edge], e[0]) call assert_equal([0, 1023], e[1][0]) + + let cand = 'x' .. repeat('a', 1024) + call assert_equal([], matchfuzzy([cand], repeat('a', 1024))) + call assert_equal([[], [], []], matchfuzzypos([cand], repeat('a', 1024))) endfunc func Test_matchfuzzy_long_candidate_mbyte() diff --git a/src/version.c b/src/version.c index 959bc0f9a..7c4111c39 100644 --- a/src/version.c +++ b/src/version.c @@ -759,6 +759,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 647, /**/ 646, /**/ -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1wYnFl-00Ewyn-CU%40256bit.org.
