Hi Bram,
On Sat, Apr 15, 2017 at 6:53 AM, Bram Moolenaar <[email protected]> wrote:
>
> Yegappan wrote:
>
>> On Sat, Apr 15, 2017 at 6:26 AM, Bram Moolenaar <[email protected]> wrote:
>> >
>> > Dominique wrote:
>> >
>> >> afl-fuzz found this case which causes use of
>> >> free memory in vim-8.0563 and older:
>> >>
>> >> $ cat bug.vim
>> >> set efm=E,%W%m,
>> >> cgetexpr ['C']
>> >> set efm=%C%m
>> >> lexpr '0'
>> >> lopen
>> >> call setqflist([], 'r')
>> >> caddbuf
>> >>
>> >> $valgrind vim -u NONE -N -S bug.vim 2> vg.log
>> >>
>> >> Doing a git bissection, I see that it's
>> >> a regression introduced by patch 7.4.1980:
>> >>
>> >> ===
>> >> commit 361c8f0e517e41f1f1d34dae328044406fde80ac
>> >> Author: Bram Moolenaar <[email protected]>
>> >> Date: Sat Jul 2 15:41:47 2016 +0200
>> >>
>> >> patch 7.4.1980
>> >> Problem: 'errorformat' is parsed for every call to ":caddexpr".
>> >> Can't add
>> >> to two location lists asynchronously.
>> >> Solution: Keep the previously parsed data when appropriate. (mostly
>> >> by
>> >> Yegappan Lakshmanan)
>> >> ===
>> >
>> > Thanks. Looks it happens because of not resetting qf_last.
>> > I made a patch.
>> >
>>
>> I just started looking into this. By that time, you have already
>> sent out the patch :-).
>
> I'm probably faster because I'm in a train :-).
>
While trying to convert the above into a test case, I noticed
a problem. After executing the following sequence of commands,
two quickfix lists should be present. But only one is present.
This is because qf_multiline is not set to false.
cgetexpr ["Red", "Green", "Blue"]
set efm=%W%m
cgetexpr ["BSD", "Linux", "GNU"]
set efm=%C%m
lexpr ["One", "Two", "Three"]
lopen
call setqflist([], 'r')
caddbuf
The attached patch fixes this problem. I have also added some other
additional test cases.
- Yegappan
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/src/quickfix.c b/src/quickfix.c
index d2921b21c..9ad4255a0 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -2750,12 +2750,18 @@ qf_free(qf_info_T *qi, int idx)
vim_free(qi->qf_lists[idx].qf_title);
qi->qf_lists[idx].qf_title = NULL;
qi->qf_lists[idx].qf_index = 0;
+ qi->qf_lists[idx].qf_start = NULL;
qi->qf_lists[idx].qf_last = NULL;
+ qi->qf_lists[idx].qf_ptr = NULL;
+ qi->qf_lists[idx].qf_nonevalid = TRUE;
qf_clean_dir_stack(&qi->qf_dir_stack);
qi->qf_directory = NULL;
qf_clean_dir_stack(&qi->qf_file_stack);
qi->qf_currfile = NULL;
+ qi->qf_multiline = FALSE;
+ qi->qf_multiignore = FALSE;
+ qi->qf_multiscan = FALSE;
}
/*
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 54995f787..c77f3c94c 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -24,8 +24,8 @@ func s:setup_commands(cchar)
command! -nargs=* Xgetbuffer <mods>cgetbuffer <args>
command! -nargs=* Xaddbuffer <mods>caddbuffer <args>
command! -nargs=* Xrewind <mods>crewind <args>
- command! -nargs=* -bang Xnext <mods>cnext<bang> <args>
- command! -nargs=* -bang Xprev <mods>cprev<bang> <args>
+ command! -count -nargs=* -bang Xnext <mods><count>cnext<bang> <args>
+ command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
command! -nargs=* -bang Xlast <mods>clast<bang> <args>
command! -nargs=* -bang Xnfile <mods>cnfile<bang> <args>
@@ -56,8 +56,8 @@ func s:setup_commands(cchar)
command! -nargs=* Xgetbuffer <mods>lgetbuffer <args>
command! -nargs=* Xaddbuffer <mods>laddbuffer <args>
command! -nargs=* Xrewind <mods>lrewind <args>
- command! -nargs=* -bang Xnext <mods>lnext<bang> <args>
- command! -nargs=* -bang Xprev <mods>lprev<bang> <args>
+ command! -count -nargs=* -bang Xnext <mods><count>lnext<bang> <args>
+ command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
command! -nargs=* -bang Xlast <mods>llast<bang> <args>
command! -nargs=* -bang Xnfile <mods>lnfile<bang> <args>
@@ -395,7 +395,9 @@ func Xtest_browse(cchar)
Xgetexpr ['Xqftestfile1:5:Line5',
\ 'Xqftestfile1:6:Line6',
\ 'Xqftestfile2:10:Line10',
- \ 'Xqftestfile2:11:Line11']
+ \ 'Xqftestfile2:11:Line11',
+ \ 'RegularLine1',
+ \ 'RegularLine2']
Xfirst
call assert_fails('Xprev', 'E553')
@@ -407,6 +409,7 @@ func Xtest_browse(cchar)
call assert_equal('Xqftestfile1', bufname('%'))
call assert_equal(6, line('.'))
Xlast
+ Xprev
call assert_equal('Xqftestfile2', bufname('%'))
call assert_equal(11, line('.'))
call assert_fails('Xnext', 'E553')
@@ -415,6 +418,13 @@ func Xtest_browse(cchar)
call assert_equal('Xqftestfile1', bufname('%'))
call assert_equal(5, line('.'))
+ 10Xnext
+ call assert_equal('Xqftestfile2', bufname('%'))
+ call assert_equal(11, line('.'))
+ 10Xprev
+ call assert_equal('Xqftestfile1', bufname('%'))
+ call assert_equal(5, line('.'))
+
Xexpr ""
call assert_fails('Xnext', 'E42:')
@@ -455,9 +465,30 @@ func s:test_xhelpgrep(cchar)
let title_text = ':lhelpgrep quickfix'
endif
call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
+
+ " Jumping to a help topic should open the help window
+ only
+ Xnext
+ call assert_true(&buftype == 'help')
+ call assert_true(winnr('$') == 2)
+ " Jumping to the next match should reuse the help window
+ Xnext
+ call assert_true(&buftype == 'help')
+ call assert_true(winnr() == 1)
+ call assert_true(winnr('$') == 2)
+ " Jumping to the next match from the quickfix window should reuse the help
+ " window
+ Xopen
+ Xnext
+ call assert_true(&buftype == 'help')
+ call assert_true(winnr() == 1)
+ call assert_true(winnr('$') == 2)
+
" This wipes out the buffer, make sure that doesn't cause trouble.
Xclose
+ new | only
+
" Search for non existing help string
call assert_fails('Xhelpgrep a1b2c3', 'E480:')
endfunc
@@ -596,10 +627,7 @@ func Test_locationlist()
lrewind
enew
lopen
- lnext
- lnext
- lnext
- lnext
+ 4lnext
vert split
wincmd L
lopen
@@ -1057,6 +1085,25 @@ func Test_efm2()
call assert_equal(1, l[4].valid)
call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
+ " The following sequence of commands used to crash Vim
+ set efm=%W%m
+ cgetexpr ['msg1']
+ let l = getqflist()
+ call assert_equal(1, len(l), string(l))
+ call assert_equal('msg1', l[0].text)
+ set efm=%C%m
+ lexpr 'msg2'
+ let l = getloclist(0)
+ call assert_equal(1, len(l), string(l))
+ call assert_equal('msg2', l[0].text)
+ lopen
+ call setqflist([], 'r')
+ caddbuf
+ let l = getqflist()
+ call assert_equal(1, len(l), string(l))
+ call assert_equal('|| msg2', l[0].text)
+
+ new | only
let &efm = save_efm
endfunc
@@ -1387,18 +1434,18 @@ func Test_switchbuf()
let winid = win_getid()
cfirst | cnext
call assert_equal(winid, win_getid())
- cnext | cnext
+ 2cnext
call assert_equal(winid, win_getid())
- cnext | cnext
+ 2cnext
call assert_equal(winid, win_getid())
enew
set switchbuf=useopen
cfirst | cnext
call assert_equal(file1_winid, win_getid())
- cnext | cnext
+ 2cnext
call assert_equal(file2_winid, win_getid())
- cnext | cnext
+ 2cnext
call assert_equal(file2_winid, win_getid())
enew | only
@@ -1408,9 +1455,9 @@ func Test_switchbuf()
tabfirst
cfirst | cnext
call assert_equal(2, tabpagenr())
- cnext | cnext
+ 2cnext
call assert_equal(3, tabpagenr())
- cnext | cnext
+ 2cnext
call assert_equal(3, tabpagenr())
tabfirst | tabonly | enew