Skip to content

Commit ffec3c5

Browse files
committed
patch 7.4.1640
Problem: Crash when an autocommand changes a quickfix list. (Dominique) Solution: Check wether an entry is still valid. (Yegappan Lakshmanan, Hirohito Higashi)
1 parent 5f436fc commit ffec3c5

File tree

4 files changed

+95
-4
lines changed

4 files changed

+95
-4
lines changed

runtime/doc/quickfix.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*quickfix.txt* For Vim version 7.4. Last change: 2016 Mar 19
1+
*quickfix.txt* For Vim version 7.4. Last change: 2016 Mar 23
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -60,6 +60,10 @@ command with 'l'.
6060
If the current window was closed by an |autocommand| while processing a
6161
location list command, it will be aborted.
6262

63+
*E925* *E926*
64+
If the current quickfix or location list was changed by an |autocommand| while
65+
processing a quickfix or location list command, it will be aborted.
66+
6367
*:cc*
6468
:cc[!] [nr] Display error [nr]. If [nr] is omitted, the same
6569
error is displayed again. Without [!] this doesn't

src/quickfix.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,33 @@ qf_guess_filepath(char_u *filename)
14121412

14131413
}
14141414

1415+
/*
1416+
* When loading a file from the quickfix, the auto commands may modify it.
1417+
* This may invalidate the current quickfix entry. This function checks
1418+
* whether a entry is still present in the quickfix.
1419+
* Similar to location list.
1420+
*/
1421+
static int
1422+
is_qf_entry_present(qf_info_T *qi, qfline_T *qf_ptr)
1423+
{
1424+
qf_list_T *qfl;
1425+
qfline_T *qfp;
1426+
int i;
1427+
1428+
qfl = &qi->qf_lists[qi->qf_curlist];
1429+
1430+
/* Search for the entry in the current list */
1431+
for (i = 0, qfp = qfl->qf_start; i < qfl->qf_count;
1432+
++i, qfp = qfp->qf_next)
1433+
if (qfp == qf_ptr)
1434+
break;
1435+
1436+
if (i == qfl->qf_count) /* Entry is not found */
1437+
return FALSE;
1438+
1439+
return TRUE;
1440+
}
1441+
14151442
/*
14161443
* jump to a quickfix line
14171444
* if dir == FORWARD go "errornr" valid entries forward
@@ -1794,18 +1821,34 @@ qf_jump(
17941821
}
17951822
else
17961823
{
1824+
int old_qf_curlist = qi->qf_curlist;
1825+
int is_abort = FALSE;
1826+
17971827
ok = buflist_getfile(qf_ptr->qf_fnum,
17981828
(linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
17991829
if (qi != &ql_info && !win_valid(oldwin))
18001830
{
18011831
EMSG(_("E924: Current window was closed"));
1832+
is_abort = TRUE;
1833+
opened_window = FALSE;
1834+
}
1835+
else if (old_qf_curlist != qi->qf_curlist
1836+
|| !is_qf_entry_present(qi, qf_ptr))
1837+
{
1838+
if (qi == &ql_info)
1839+
EMSG(_("E925: Current quickfix was changed"));
1840+
else
1841+
EMSG(_("E926: Current location list was changed"));
1842+
is_abort = TRUE;
1843+
}
1844+
1845+
if (is_abort)
1846+
{
18021847
ok = FALSE;
18031848
qi = NULL;
18041849
qf_ptr = NULL;
1805-
opened_window = FALSE;
18061850
}
18071851
}
1808-
18091852
}
18101853

18111854
if (ok == OK)

src/testdir/test_quickfix.vim

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ function Test_locationlist_curwin_was_closed()
504504
autocmd BufReadCmd t call R(expand("<amatch>"))
505505
augroup END
506506

507-
function R(n)
507+
function! R(n)
508508
quit
509509
endfunc
510510

@@ -637,3 +637,45 @@ function! Test_efm1()
637637
call delete('Xerrorfile2')
638638
call delete('Xtestfile')
639639
endfunction
640+
641+
function XquickfixChangedByAutocmd(cchar)
642+
let Xolder = a:cchar . 'older'
643+
let Xgetexpr = a:cchar . 'getexpr'
644+
let Xrewind = a:cchar . 'rewind'
645+
if a:cchar == 'c'
646+
let Xsetlist = 'setqflist('
647+
let ErrorNr = 'E925'
648+
function! ReadFunc()
649+
colder
650+
cgetexpr []
651+
endfunc
652+
else
653+
let Xsetlist = 'setloclist(0,'
654+
let ErrorNr = 'E926'
655+
function! ReadFunc()
656+
lolder
657+
lgetexpr []
658+
endfunc
659+
endif
660+
661+
augroup testgroup
662+
au!
663+
autocmd BufReadCmd t call ReadFunc()
664+
augroup END
665+
666+
bwipe!
667+
let words = [ "a", "b" ]
668+
let qflist = []
669+
for word in words
670+
call add(qflist, {'filename': 't'})
671+
exec "call " . Xsetlist . "qflist, '')"
672+
endfor
673+
exec "call assert_fails('" . Xrewind . "', '" . ErrorNr . ":')"
674+
675+
augroup! testgroup
676+
endfunc
677+
678+
function Test_quickfix_was_changed_by_autocmd()
679+
call XquickfixChangedByAutocmd('c')
680+
call XquickfixChangedByAutocmd('l')
681+
endfunction

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,8 @@ static char *(features[]) =
748748

749749
static int included_patches[] =
750750
{ /* Add new patch number below this line */
751+
/**/
752+
1640,
751753
/**/
752754
1639,
753755
/**/

0 commit comments

Comments
 (0)