To: vim_dev@googlegroups.com Subject: Patch 9.0.1499 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.1499 Problem: Using uninitialized memory with fuzzy matching. Solution: Initialize the arrays used to store match positions. Files: src/quickfix.c, src/search.c, src/testdir/test_matchfuzzy.vim *** ../vim-9.0.1498/src/quickfix.c 2023-03-07 17:45:07.188247898 +0000 --- src/quickfix.c 2023-04-29 21:33:18.094677779 +0100 *************** *** 6058,6063 **** --- 6058,6065 ---- 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,6072 **** { // Regular expression match while (vim_regexec_multi(regmatch, curwin, buf, lnum, ! col, NULL) > 0) { // Pass the buffer number so that it gets used even for a // dummy buffer, unless duplicate_name is set, then the --- 6068,6074 ---- { // Regular expression match while (vim_regexec_multi(regmatch, curwin, buf, lnum, ! 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,6117 **** --- 6114,6120 ---- 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 *** ../vim-9.0.1498/src/search.c 2023-03-07 17:45:07.188247898 +0000 --- src/search.c 2023-04-29 21:33:13.934669160 +0100 *************** *** 4422,4435 **** // 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; // "Copy-on-Write" srcMatches into matches if (first_match && srcMatches) { --- 4431,4444 ---- // Found match if (vim_tolower(c1) == vim_tolower(c2)) { // 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,4447 **** } // Recursive call that "skips" this match ! if (has_mbyte) ! next_char = str + (*mb_ptr2len)(str); ! else ! next_char = str + 1; if (fuzzy_match_recursive(fuzpat, next_char, strIdx + 1, &recursiveScore, strBegin, strLen, matches, recursiveMatches, --- 4447,4453 ---- } // Recursive call that "skips" this match ! 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,4513 **** * 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'. */ int fuzzy_match( --- 4512,4519 ---- * 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". */ int fuzzy_match( *** ../vim-9.0.1498/src/testdir/test_matchfuzzy.vim 2022-08-30 19:48:17.206760205 +0100 --- src/testdir/test_matchfuzzy.vim 2023-04-29 21:27:23.561587160 +0100 *************** *** 2,7 **** --- 2,8 ---- source shared.vim source check.vim + source term_util.vim " Test for matchfuzzy() func Test_matchfuzzy() *************** *** 253,256 **** --- 254,283 ---- 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 *** ../vim-9.0.1498/src/version.c 2023-04-29 14:25:59.179203254 +0100 --- src/version.c 2023-04-29 21:13:19.410164546 +0100 *************** *** 697,698 **** --- 697,700 ---- { /* Add new patch number below this line */ + /**/ + 1499, /**/ -- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///