]> granicus.if.org Git - vim/commitdiff
patch 8.2.1677: memory access errors when calling setloclist() in autocommand v8.2.1677
authorBram Moolenaar <Bram@vim.org>
Sun, 13 Sep 2020 20:21:22 +0000 (22:21 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 13 Sep 2020 20:21:22 +0000 (22:21 +0200)
Problem:    Memory access errors when calling setloclist() in an autocommand.
Solution:   Give an error if the list was changed unexpectedly. (closes #6946)

src/quickfix.c
src/testdir/test_quickfix.vim
src/version.c

index c8858b456e2de24d74708d5d8c230e83bc7d9f43..43d2d3fbd5067a821368ad23861614a6ee3103aa 100644 (file)
@@ -216,7 +216,9 @@ static char_u       *e_no_more_items = (char_u *)N_("E553: No more items");
 static char_u   *qf_last_bufname = NULL;
 static bufref_T  qf_last_bufref = {NULL, 0, 0};
 
-static char    *e_loc_list_changed =
+static char    *e_current_quickfix_list_was_changed =
+                                N_("E925: Current quickfix list was changed");
+static char    *e_current_location_list_was_changed =
                                 N_("E926: Current location list was changed");
 
 /*
@@ -3108,6 +3110,7 @@ qf_jump_edit_buffer(
        int             *opened_window)
 {
     qf_list_T  *qfl = qf_get_curlist(qi);
+    int                old_changedtick = qfl->qf_changedtick;
     qfltype_T  qfl_type = qfl->qfl_type;
     int                retval = OK;
     int                old_qf_curlist = qi->qf_curlist;
@@ -3146,17 +3149,20 @@ qf_jump_edit_buffer(
 
     if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid))
     {
-       emsg(_("E925: Current quickfix was changed"));
+       emsg(_(e_current_quickfix_list_was_changed));
        return NOTDONE;
     }
 
+    // Check if the list was changed.  The pointers may happen to be identical,
+    // thus also check qf_changedtick.
     if (old_qf_curlist != qi->qf_curlist
+           || old_changedtick != qfl->qf_changedtick
            || !is_qf_entry_present(qfl, qf_ptr))
     {
        if (qfl_type == QFLT_QUICKFIX)
-           emsg(_("E925: Current quickfix was changed"));
+           emsg(_(e_current_quickfix_list_was_changed));
        else
-           emsg(_(e_loc_list_changed));
+           emsg(_(e_current_location_list_was_changed));
        return NOTDONE;
     }
 
@@ -3264,10 +3270,25 @@ qf_jump_open_window(
        int             newwin,
        int             *opened_window)
 {
+    qf_list_T  *qfl = qf_get_curlist(qi);
+    int                old_changedtick = qfl->qf_changedtick;
+    int                old_qf_curlist = qi->qf_curlist;
+    qfltype_T  qfl_type = qfl->qfl_type;
+
     // For ":helpgrep" find a help window or open one.
     if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0))
        if (jump_to_help_window(qi, newwin, opened_window) == FAIL)
            return FAIL;
+    if (old_qf_curlist != qi->qf_curlist
+           || old_changedtick != qfl->qf_changedtick
+           || !is_qf_entry_present(qfl, qf_ptr))
+    {
+       if (qfl_type == QFLT_QUICKFIX)
+           emsg(_(e_current_quickfix_list_was_changed));
+       else
+           emsg(_(e_current_location_list_was_changed));
+       return FAIL;
+    }
 
     // If currently in the quickfix window, find another window to show the
     // file in.
@@ -3282,6 +3303,16 @@ qf_jump_open_window(
                                                opened_window) == FAIL)
            return FAIL;
     }
+    if (old_qf_curlist != qi->qf_curlist
+           || old_changedtick != qfl->qf_changedtick
+           || !is_qf_entry_present(qfl, qf_ptr))
+    {
+       if (qfl_type == QFLT_QUICKFIX)
+           emsg(_(e_current_quickfix_list_was_changed));
+       else
+           emsg(_(e_current_location_list_was_changed));
+       return FAIL;
+    }
 
     return OK;
 }
@@ -5834,7 +5865,7 @@ vgr_qflist_valid(
        if (wp != NULL)
        {
            // An autocmd has freed the location list.
-           emsg(_(e_loc_list_changed));
+           emsg(_(e_current_location_list_was_changed));
            return FALSE;
        }
        else
index 1e753a467c89d10f8aa68deaa5c1b80bbd204417..0d8e35538b940177b245128f061d58baca74bce2 100644 (file)
@@ -1430,6 +1430,30 @@ func Test_quickfix_was_changed_by_autocmd()
   call XquickfixChangedByAutocmd('l')
 endfunc
 
+func Test_setloclist_in_autocommand()
+  call writefile(['test1', 'test2'], 'Xfile')
+  edit Xfile
+  let s:bufnr = bufnr()
+  call setloclist(1,
+        \ [{'bufnr' : s:bufnr, 'lnum' : 1, 'text' : 'test1'},
+        \  {'bufnr' : s:bufnr, 'lnum' : 2, 'text' : 'test2'}])
+
+  augroup Test_LocList
+    au!
+    autocmd BufEnter * call setloclist(1,
+          \ [{'bufnr' : s:bufnr, 'lnum' : 1, 'text' : 'test1'},
+          \  {'bufnr' : s:bufnr, 'lnum' : 2, 'text' : 'test2'}], 'r')
+  augroup END
+
+  lopen
+  call assert_fails('exe "normal j\<CR>"', 'E926:')
+
+  augroup Test_LocList
+    au!
+  augroup END
+  call delete('Xfile')
+endfunc
+
 func Test_caddbuffer_to_empty()
   helpgr quickfix
   call setqflist([], 'r')
index b8891ff66723fc44e0fd6deb4fce72fd4ec42766..0d0ea4dd8457091b358958596d578f5d77e0f8e2 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1677,
 /**/
     1676,
 /**/