diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-05-01 20:46:52 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-05-01 20:46:52 +0200 |
commit | 4475b623960671898dac6a72b13a8d140402afa6 (patch) | |
tree | 19b0d5a28ad7aa3375cb5f8319209eba5229db17 | |
parent | beb9cb19c660484488a71a25eda46ab0fa579278 (diff) | |
download | vim-4475b623960671898dac6a72b13a8d140402afa6.zip |
patch 8.0.0596: crash when complete() called after complete_add()
Problem: Crash when complete() is called after complete_add() in
'completefunc'. (Lifepillar)
Solution: Bail out if compl_pattern is NULL. (closes #1668)
Also avoid using freed memory.
-rw-r--r-- | src/edit.c | 29 | ||||
-rw-r--r-- | src/testdir/test_popup.vim | 43 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 64 insertions, 10 deletions
diff --git a/src/edit.c b/src/edit.c index 0153f3b9d..89a5fae07 100644 --- a/src/edit.c +++ b/src/edit.c @@ -96,6 +96,7 @@ struct compl_S static compl_T *compl_first_match = NULL; static compl_T *compl_curr_match = NULL; static compl_T *compl_shown_match = NULL; +static compl_T *compl_old_match = NULL; /* After using a cursor key <Enter> selects a match in the popup menu, * otherwise it inserts a line break. */ @@ -3431,6 +3432,7 @@ ins_compl_free(void) } while (compl_curr_match != NULL && compl_curr_match != compl_first_match); compl_first_match = compl_curr_match = NULL; compl_shown_match = NULL; + compl_old_match = NULL; } static void @@ -4272,7 +4274,6 @@ ins_compl_get_exp(pos_T *ini) char_u *ptr; char_u *dict = NULL; int dict_f = 0; - compl_T *old_match; int set_match_pos; if (!compl_started) @@ -4286,7 +4287,7 @@ ins_compl_get_exp(pos_T *ini) last_match_pos = first_match_pos = *ini; } - old_match = compl_curr_match; /* remember the last current match */ + compl_old_match = compl_curr_match; /* remember the last current match */ pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos; /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */ for (;;) @@ -4388,6 +4389,11 @@ ins_compl_get_exp(pos_T *ini) } } + /* If complete() was called then compl_pattern has been reset. The + * following won't work then, bail out. */ + if (compl_pattern == NULL) + break; + switch (type) { case -1: @@ -4621,7 +4627,7 @@ ins_compl_get_exp(pos_T *ini) /* check if compl_curr_match has changed, (e.g. other type of * expansion added something) */ - if (type != 0 && compl_curr_match != old_match) + if (type != 0 && compl_curr_match != compl_old_match) found_new_match = OK; /* break the loop for specialized modes (use 'complete' just for the @@ -4660,13 +4666,16 @@ ins_compl_get_exp(pos_T *ini) || (ctrl_x_mode != 0 && !CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))) i = ins_compl_make_cyclic(); - /* If several matches were added (FORWARD) or the search failed and has - * just been made cyclic then we have to move compl_curr_match to the next - * or previous entry (if any) -- Acevedo */ - compl_curr_match = compl_direction == FORWARD ? old_match->cp_next - : old_match->cp_prev; - if (compl_curr_match == NULL) - compl_curr_match = old_match; + if (compl_old_match != NULL) + { + /* If several matches were added (FORWARD) or the search failed and has + * just been made cyclic then we have to move compl_curr_match to the + * next or previous entry (if any) -- Acevedo */ + compl_curr_match = compl_direction == FORWARD ? compl_old_match->cp_next + : compl_old_match->cp_prev; + if (compl_curr_match == NULL) + compl_curr_match = compl_old_match; + } return i; } diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim index 4789ca76b..25d766f7b 100644 --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -570,4 +570,47 @@ func Test_completion_comment_formatting() bwipe! endfunc +fun MessCompleteMonths() + for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep") + call complete_add(m) + if complete_check() + break + endif + endfor + return [] +endfun + +fun MessCompleteMore() + call complete(1, split("Oct Nov Dec")) + return [] +endfun + +fun MessComplete(findstart, base) + if a:findstart + let line = getline('.') + let start = col('.') - 1 + while start > 0 && line[start - 1] =~ '\a' + let start -= 1 + endwhile + return start + else + call MessCompleteMonths() + call MessCompleteMore() + return [] + endif +endf + +func Test_complete_func_mess() + " Calling complete() after complete_add() in 'completefunc' is wrong, but it + " should not crash. + set completefunc=MessComplete + new + call setline(1, 'Ju') + call feedkeys("A\<c-x>\<c-u>/\<esc>", 'tx') + call assert_equal('Oct/Oct', getline(1)) + bwipe! + set completefunc= +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 8895b73b0..f31a946dc 100644 --- a/src/version.c +++ b/src/version.c @@ -765,6 +765,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 596, +/**/ 595, /**/ 594, |