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
index 0153f3b..89a5fae 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -96,6 +96,7 @@
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 @@
} 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 @@
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 @@
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 @@
}
}
+ /* 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 @@
/* 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 @@
|| (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;
}