summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2022-08-27 20:59:57 +0100
committerBram Moolenaar <Bram@vim.org>2022-08-27 20:59:57 +0100
commit6d24a51b94beb1991cddce221f90b455e2d50db7 (patch)
treee9379865255d99e36675221bc1f39af42c92bd8a
parent07ea5f1509fe8dafe3262ed2702b4d0fc99e288b (diff)
downloadvim-git-9.0.0286.tar.gz
patch 9.0.0286: using freed memory when location list changed in autocmdv9.0.0286
Problem: Using freed memory when location list changed in autocmd. Solution: Return QF_ABORT and handle it. (Yegappan Lakshmanan, closes #10993)
-rw-r--r--src/quickfix.c28
-rw-r--r--src/testdir/test_quickfix.vim17
-rw-r--r--src/version.c2
3 files changed, 37 insertions, 10 deletions
diff --git a/src/quickfix.c b/src/quickfix.c
index 6af62e8df..78f6880d8 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -594,6 +594,7 @@ enum {
QF_NOMEM = 3,
QF_IGNORE_LINE = 4,
QF_MULTISCAN = 5,
+ QF_ABORT = 6
};
/*
@@ -3153,7 +3154,7 @@ qf_jump_to_usable_window(int qf_fnum, int newwin, int *opened_window)
/*
* Edit the selected file or help file.
* Returns OK if successfully edited the file, FAIL on failing to open the
- * buffer and NOTDONE if the quickfix/location list was freed by an autocmd
+ * buffer and QF_ABORT if the quickfix/location list was freed by an autocmd
* when opening the buffer.
*/
static int
@@ -3199,14 +3200,14 @@ qf_jump_edit_buffer(
{
emsg(_(e_current_window_was_closed));
*opened_window = FALSE;
- return NOTDONE;
+ return QF_ABORT;
}
}
if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid))
{
emsg(_(e_current_quickfix_list_was_changed));
- return NOTDONE;
+ return QF_ABORT;
}
// Check if the list was changed. The pointers may happen to be identical,
@@ -3219,7 +3220,7 @@ qf_jump_edit_buffer(
emsg(_(e_current_quickfix_list_was_changed));
else
emsg(_(e_current_location_list_was_changed));
- return NOTDONE;
+ return QF_ABORT;
}
return retval;
@@ -3317,7 +3318,8 @@ qf_jump_print_msg(
* a new window.
* Returns OK if successfully jumped or opened a window. Returns FAIL if not
* able to jump/open a window. Returns NOTDONE if a file is not associated
- * with the entry.
+ * with the entry. Returns QF_ABORT if the quickfix/location list was modified
+ * by an autocmd.
*/
static int
qf_jump_open_window(
@@ -3344,7 +3346,7 @@ qf_jump_open_window(
emsg(_(e_current_quickfix_list_was_changed));
else
emsg(_(e_current_location_list_was_changed));
- return FAIL;
+ return QF_ABORT;
}
// If currently in the quickfix window, find another window to show the
@@ -3368,7 +3370,7 @@ qf_jump_open_window(
emsg(_(e_current_quickfix_list_was_changed));
else
emsg(_(e_current_location_list_was_changed));
- return FAIL;
+ return QF_ABORT;
}
return OK;
@@ -3379,7 +3381,7 @@ qf_jump_open_window(
* particular line/column, adjust the folds and display a message about the
* jump.
* Returns OK on success and FAIL on failing to open the file/buffer. Returns
- * NOTDONE if the quickfix/location list is freed by an autocmd when opening
+ * QF_ABORT if the quickfix/location list is freed by an autocmd when opening
* the file.
*/
static int
@@ -3508,14 +3510,20 @@ qf_jump_newwin(qf_info_T *qi,
retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window);
if (retval == FAIL)
goto failed;
+ if (retval == QF_ABORT)
+ {
+ qi = NULL;
+ qf_ptr = NULL;
+ goto theend;
+ }
if (retval == NOTDONE)
goto theend;
retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, prev_winid,
&opened_window, old_KeyTyped, print_message);
- if (retval == NOTDONE)
+ if (retval == QF_ABORT)
{
- // Quickfix/location list is freed by an autocmd
+ // Quickfix/location list was modified by an autocmd
qi = NULL;
qf_ptr = NULL;
}
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 762fa8d8d..31d36ef1d 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -6363,5 +6363,22 @@ func Test_quickfixtextfunc_recursive()
cclose
endfunc
+" Test for replacing the location list from an autocmd. This used to cause a
+" read from freed memory.
+func Test_loclist_replace_autocmd()
+ %bw!
+ call setloclist(0, [], 'f')
+ let s:bufnr = bufnr()
+ cal setloclist(0, [{'0': 0, '': ''}])
+ au BufEnter * cal setloclist(1, [{'t': ''}, {'bufnr': s:bufnr}], 'r')
+ lopen
+ try
+ exe "norm j\<CR>"
+ catch
+ endtry
+ lnext
+ %bw!
+ call setloclist(0, [], 'f')
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 6b4bdfab2..206548373 100644
--- a/src/version.c
+++ b/src/version.c
@@ -708,6 +708,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 286,
+/**/
285,
/**/
284,