# HG changeset patch # User Christian Brabandt # Date 1493665204 -7200 # Node ID 328a9ee98fb2c7cb4f93374cfc04bc18ac80b47d # Parent e9a041bb30ebb36c25ee300662e498b3052159da patch 8.0.0596: crash when complete() called after complete_add() commit https://github.com/vim/vim/commit/4475b623960671898dac6a72b13a8d140402afa6 Author: Bram Moolenaar Date: Mon May 1 20:46:52 2017 +0200 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. diff --git a/src/edit.c b/src/edit.c --- 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 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 --- 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\\/\", '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 --- 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,