Merge pull request #17839 from zeertzjq/vim-8.2.4281

vim-patch:8.2.{4281,4327}: fix two crashes with quickfix and wiping buffer
This commit is contained in:
zeertzjq
2022-03-26 12:59:34 +08:00
committed by GitHub
2 changed files with 140 additions and 86 deletions

View File

@@ -1284,8 +1284,10 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
while (jumpidx != curwin->w_jumplistidx) {
buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
if (buf != NULL) {
if (buf == curbuf || !buf->b_p_bl) {
buf = NULL; // skip current and unlisted bufs
// Skip current and unlisted bufs. Also skip a quickfix
// buffer, it might be deleted soon.
if (buf == curbuf || !buf->b_p_bl || bt_quickfix(buf)) {
buf = NULL;
} else if (buf->b_ml.ml_mfp == NULL) {
// skip unloaded buf, but may keep it for later
if (bp == NULL) {
@@ -1323,7 +1325,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
continue;
}
// in non-help buffer, try to skip help buffers, and vv
if (buf->b_help == curbuf->b_help && buf->b_p_bl) {
if (buf->b_help == curbuf->b_help && buf->b_p_bl && !bt_quickfix(buf)) {
if (buf->b_ml.ml_mfp != NULL) { // found loaded buffer
break;
}
@@ -1343,7 +1345,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
}
if (buf == NULL) { // No loaded buffer, find listed one
FOR_ALL_BUFFERS(buf2) {
if (buf2->b_p_bl && buf2 != curbuf) {
if (buf2->b_p_bl && buf2 != curbuf && !bt_quickfix(buf2)) {
buf = buf2;
break;
}
@@ -1355,6 +1357,9 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
} else {
buf = curbuf->b_prev;
}
if (bt_quickfix(buf)) {
buf = NULL;
}
}
}
@@ -1486,8 +1491,15 @@ void set_curbuf(buf_T *buf, int action)
// An autocommand may have deleted "buf", already entered it (e.g., when
// it did ":bunload") or aborted the script processing!
// If curwin->w_buffer is null, enter_buffer() will make it valid again
if ((buf_valid(buf) && buf != curbuf && !aborting()) || curwin->w_buffer == NULL) {
enter_buffer(buf);
bool valid = buf_valid(buf);
if ((valid && buf != curbuf && !aborting()) || curwin->w_buffer == NULL) {
// If the buffer is not valid but curwin->w_buffer is NULL we must
// enter some buffer. Using the last one is hopefully OK.
if (!valid) {
enter_buffer(lastbuf);
} else {
enter_buffer(buf);
}
if (old_tw != curbuf->b_p_tw) {
check_colorcolumn(curwin);
}

View File

@@ -796,101 +796,102 @@ func ReadTestProtocol(name)
endfunc
func Test_locationlist()
enew
enew
augroup testgroup
au!
autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
augroup END
augroup testgroup
au!
autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
augroup END
let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
let qflist = []
for word in words
call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
" NOTE: problem 1:
" intentionally not setting 'lnum' so that the quickfix entries are not
" valid
eval qflist->setloclist(0, ' ')
endfor
let qflist = []
for word in words
call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
" NOTE: problem 1:
" intentionally not setting 'lnum' so that the quickfix entries are not
" valid
eval qflist->setloclist(0, ' ')
endfor
" Test A
lrewind
enew
lopen
4lnext
vert split
wincmd L
lopen
wincmd p
lnext
let fileName = expand("%")
wincmd p
let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
let fileName = substitute(fileName, '\\', '/', 'g')
let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
call assert_equal("test://bar.txt", fileName)
call assert_equal("test://bar.txt", locationListFileName)
" Test A
lrewind
enew
lopen
4lnext
vert split
wincmd L
lopen
wincmd p
lnext
let fileName = expand("%")
wincmd p
let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
let fileName = substitute(fileName, '\\', '/', 'g')
let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
call assert_equal("test://bar.txt", fileName)
call assert_equal("test://bar.txt", locationListFileName)
wincmd n | only
wincmd n | only
" Test B:
lrewind
lopen
2
exe "normal \<CR>"
wincmd p
3
exe "normal \<CR>"
wincmd p
4
exe "normal \<CR>"
call assert_equal(2, winnr('$'))
wincmd n | only
" Test B:
lrewind
lopen
2
exe "normal \<CR>"
wincmd p
3
exe "normal \<CR>"
wincmd p
4
exe "normal \<CR>"
call assert_equal(2, winnr('$'))
wincmd n | only
" Test C:
lrewind
lopen
" Let's move the location list window to the top to check whether it (the
" first window found) will be reused when we try to open new windows:
wincmd K
2
exe "normal \<CR>"
wincmd p
3
exe "normal \<CR>"
wincmd p
4
exe "normal \<CR>"
1wincmd w
call assert_equal('quickfix', &buftype)
2wincmd w
let bufferName = expand("%")
let bufferName = substitute(bufferName, '\\', '/', 'g')
call assert_equal('test://quux.txt', bufferName)
" Test C:
lrewind
lopen
" Let's move the location list window to the top to check whether it (the
" first window found) will be reused when we try to open new windows:
wincmd K
2
exe "normal \<CR>"
wincmd p
3
exe "normal \<CR>"
wincmd p
4
exe "normal \<CR>"
1wincmd w
call assert_equal('quickfix', &buftype)
2wincmd w
let bufferName = expand("%")
let bufferName = substitute(bufferName, '\\', '/', 'g')
call assert_equal('test://quux.txt', bufferName)
wincmd n | only
wincmd n | only
augroup! testgroup
augroup! testgroup
endfunc
func Test_locationlist_curwin_was_closed()
augroup testgroup
au!
autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
augroup END
augroup testgroup
au!
autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
augroup END
func! R(n)
quit
endfunc
func! R(n)
quit
endfunc
new
let q = []
call add(q, {'filename': 'test_curwin.txt' })
call setloclist(0, q)
call assert_fails('lrewind', 'E924:')
new
let q = []
call add(q, {'filename': 'test_curwin.txt' })
call setloclist(0, q)
call assert_fails('lrewind', 'E924:')
augroup! testgroup
augroup! testgroup
delfunc R
endfunc
func Test_locationlist_cross_tab_jump()
@@ -5489,4 +5490,45 @@ func Test_two_qf_windows()
%bw!
endfunc
" Weird sequence of commands that caused entering a wiped-out buffer
func Test_lopen_bwipe()
func R()
silent! tab lopen
e x
silent! lfile
endfunc
cal R()
cal R()
cal R()
bw!
delfunc R
endfunc
" Another sequence of commands that caused all buffers to be wiped out
func Test_lopen_bwipe_all()
let lines =<< trim END
func R()
silent! tab lopen
e foo
silent! lfile
endfunc
cal R()
exe "norm \<C-W>\<C-V>0"
cal R()
bwipe
call writefile(['done'], 'Xresult')
qall!
END
call writefile(lines, 'Xscript')
if RunVim([], [], '--clean -n -S Xscript')
call assert_equal(['done'], readfile('Xresult'))
endif
call delete('Xscript')
call delete('Xresult')
endfunc
" vim: shiftwidth=2 sts=2 expandtab