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.

Raspunde prin e-mail lui