changeset 32335:9c034274034b v9.0.1499

patch 9.0.1499: using uninitialized memory with fuzzy matching Commit: https://github.com/vim/vim/commit/caf642c25de526229264cab9425e7c9979f3509b Author: Bram Moolenaar <Bram@vim.org> Date: Sat Apr 29 21:38:04 2023 +0100 patch 9.0.1499: using uninitialized memory with fuzzy matching Problem: Using uninitialized memory with fuzzy matching. Solution: Initialize the arrays used to store match positions.
author Bram Moolenaar <Bram@vim.org>
date Sat, 29 Apr 2023 22:45:03 +0200
parents 33eb1fc6e886
children f3c9704e69cc
files src/quickfix.c src/search.c src/testdir/test_matchfuzzy.vim src/version.c
diffstat 4 files changed, 40 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -6058,6 +6058,8 @@ vgr_match_buflines(
     long	lnum;
     colnr_T	col;
     int		pat_len = (int)STRLEN(spat);
+    if (pat_len > MAX_FUZZY_MATCHES)
+	pat_len = MAX_FUZZY_MATCHES;
 
     for (lnum = 1; lnum <= buf->b_ml.ml_line_count && *tomatch > 0; ++lnum)
     {
@@ -6066,7 +6068,7 @@ vgr_match_buflines(
 	{
 	    // Regular expression match
 	    while (vim_regexec_multi(regmatch, curwin, buf, lnum,
-			col, NULL) > 0)
+								col, NULL) > 0)
 	    {
 		// Pass the buffer number so that it gets used even for a
 		// dummy buffer, unless duplicate_name is set, then the
@@ -6112,6 +6114,7 @@ vgr_match_buflines(
 	    int_u   sz = ARRAY_LENGTH(matches);
 
 	    // Fuzzy string match
+	    CLEAR_FIELD(matches);
 	    while (fuzzy_match(str + col, spat, FALSE, &score, matches, sz) > 0)
 	    {
 		// Pass the buffer number so that it gets used even for a
--- a/src/search.c
+++ b/src/search.c
@@ -4422,14 +4422,14 @@ fuzzy_match_recursive(
 	// Found match
 	if (vim_tolower(c1) == vim_tolower(c2))
 	{
-	    int_u	recursiveMatches[MAX_FUZZY_MATCHES];
-	    int		recursiveScore = 0;
-	    char_u	*next_char;
-
 	    // Supplied matches buffer was too short
 	    if (nextMatch >= maxMatches)
 		return 0;
 
+	    int		recursiveScore = 0;
+	    int_u	recursiveMatches[MAX_FUZZY_MATCHES];
+	    CLEAR_FIELD(recursiveMatches);
+
 	    // "Copy-on-Write" srcMatches into matches
 	    if (first_match && srcMatches)
 	    {
@@ -4438,10 +4438,7 @@ fuzzy_match_recursive(
 	    }
 
 	    // Recursive call that "skips" this match
-	    if (has_mbyte)
-		next_char = str + (*mb_ptr2len)(str);
-	    else
-		next_char = str + 1;
+	    char_u *next_char = str + (has_mbyte ? (*mb_ptr2len)(str) : 1);
 	    if (fuzzy_match_recursive(fuzpat, next_char, strIdx + 1,
 			&recursiveScore, strBegin, strLen, matches,
 			recursiveMatches,
@@ -4506,8 +4503,8 @@ fuzzy_match_recursive(
  * Uses char_u for match indices. Therefore patterns are limited to
  * MAX_FUZZY_MATCHES characters.
  *
- * Returns TRUE if 'pat_arg' matches 'str'. Also returns the match score in
- * 'outScore' and the matching character positions in 'matches'.
+ * Returns TRUE if "pat_arg" matches "str". Also returns the match score in
+ * "outScore" and the matching character positions in "matches".
  */
     int
 fuzzy_match(
--- a/src/testdir/test_matchfuzzy.vim
+++ b/src/testdir/test_matchfuzzy.vim
@@ -2,6 +2,7 @@
 
 source shared.vim
 source check.vim
+source term_util.vim
 
 " Test for matchfuzzy()
 func Test_matchfuzzy()
@@ -253,4 +254,30 @@ func Test_matchfuzzy_limit()
   call assert_equal([{'id': 5, 'val': 'crayon'}], l->matchfuzzy('c', #{key: 'val', limit: 1}))
 endfunc
 
+" This was using uninitialized memory
+func Test_matchfuzzy_initialized()
+  CheckRunVimInTerminal
+
+  " This can take a very long time (esp. when using valgrind).  Run in a
+  " separate Vim instance and kill it after two seconds.  We only check for
+  " memory errors.
+  let lines =<< trim END
+      lvimgrep [ss [fg*
+  END
+  call writefile(lines, 'XTest_matchfuzzy', 'D')
+
+  let buf = RunVimInTerminal('-u NONE -X -Z', {})
+  call term_sendkeys(buf, ":source XTest_matchfuzzy\n")
+  call TermWait(buf, 2000)
+
+  let job = term_getjob(buf)
+  if job_status(job) == "run"
+    call job_stop(job, "int")
+    call TermWait(buf, 50)
+  endif
+
+  " clean up
+  call StopVimInTerminal(buf)
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1499,
+/**/
     1498,
 /**/
     1497,