Hi, On Mon, Mar 21, 2016 at 2:45 AM, Dominique Pellé <dominique.pe...@gmail.com> wrote: > Hi > > afl-fuzz found another crash with use of freed memory in vim-7.4.1627 > (and older) in quickfix code. This is a different bug that the one fixed > recently in Vim-7.4.1592: >
The attached patch fixes this issue. These issues are caused by autocmds modifying the location list while the location list is being used. - Yegappan > > $ cat > crash.vim <<EOF > fun! R() > lolder > lgetexpr [] > endfun > > autocmd BufReadCmd * call R() > let words = [ "a", "b" ] > let qflist = [] > for word in words > call add(qflist, {'filename': 't'}) > call setloclist(0, qflist, ' ') > endfor > lrewind > EOF > > $ vim -u NONE -N -S crash.vim > Vim: Caught deadly signal SEGV > > Vim: Finished. > Segmentation fault > > -- -- 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 vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
diff --git a/src/quickfix.c b/src/quickfix.c index 06e50da..24ef119 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -1413,6 +1413,32 @@ qf_guess_filepath(char_u *filename) } /* + * When loading a file from the location list, the auto commands may modify the + * location list. This may invalidate the current location list entry. This + * function checks whether a entry is still present in the location list. + */ + static int +is_ll_entry_present(qf_info_T *qi, qfline_T *qf_ptr) +{ + qf_list_T *qfl; + qfline_T *qfp; + int i; + + qfl = &qi->qf_lists[qi->qf_curlist]; + + /* Search for the entry in the current list */ + for (i = 0, qfp = qfl->qf_start; i < qfl->qf_count; + ++i, qfp = qfp->qf_next) + if (qfp == qf_ptr) + break; + + if (i == qfl->qf_count) /* Entry is not found */ + return FALSE; + + return TRUE; +} + +/* * jump to a quickfix line * if dir == FORWARD go "errornr" valid entries forward * if dir == BACKWARD go "errornr" valid entries backward @@ -1796,16 +1822,30 @@ win_found: { ok = buflist_getfile(qf_ptr->qf_fnum, (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); - if (qi != &ql_info && !win_valid(oldwin)) + if (qi != &ql_info) { - EMSG(_("E924: Current window was closed")); - ok = FALSE; - qi = NULL; - qf_ptr = NULL; - opened_window = FALSE; + /* + * Location list. When loading the buffer using + * buflist_getfile(), autocommands are triggered which may + * alter the location list. Check whether the location list + * window and the location list are still valid. + */ + if (!win_valid(oldwin)) + { + EMSG(_("E924: Current window was closed")); + ok = FALSE; + qi = NULL; + qf_ptr = NULL; + opened_window = FALSE; + } else if (!is_ll_entry_present(qi, qf_ptr)) + { + EMSG(_("E925: Location list is different")); + ok = FALSE; + qi = NULL; + qf_ptr = NULL; + } } } - } if (ok == OK) diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index 07c465d..39a55cb 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -637,3 +637,23 @@ function! Test_efm1() call delete('Xerrorfile2') call delete('Xtestfile') endfunction + +" Test for removing the location list while it is still in use +function Test_locationlist_curlist_invalid() + fun! Reset_Loc_List() + lolder + lgetexpr [] + endfun + + autocmd BufReadCmd x call Reset_Loc_List() + + let words = [ "a", "b" ] + let qflist = [] + for word in words + call add(qflist, {'filename': 'x'}) + call setloclist(0, qflist, ' ') + endfor + call assert_fails('lrewind', 'E925:') + + autocmd! BufReadCmd +endfunction