Commit: patch 9.2.0647: matchfuzzypos() false exact match for long equal-length candidates

0 views
Skip to first unread message

Christian Brabandt

unread,
12:00 PM (2 hours ago) 12:00 PM
to vim...@googlegroups.com
patch 9.2.0647: matchfuzzypos() false exact match for long equal-length candidates

Commit: https://github.com/vim/vim/commit/1437f478158e71effdbcec3df5caa95af9b9a50a
Author: glepnir <gleph...@gmail.com>
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 <gleph...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

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,
/**/
Reply all
Reply to author
Forward
0 new messages