vim-patch:8.2.4281: using freed memory with :lopen and :bwipe

Problem:    Using freed memory with :lopen and :bwipe.
Solution:   Do not use a wiped out buffer.
9b4a80a665

Cherry-pick some indent changes from patch 8.2.1432.
This commit is contained in:
zeertzjq 2022-03-24 12:29:26 +08:00
parent 9530c2d6d8
commit 19bbc43947
2 changed files with 106 additions and 82 deletions

View File

@ -1486,8 +1486,15 @@ void set_curbuf(buf_T *buf, int action)
// An autocommand may have deleted "buf", already entered it (e.g., when // An autocommand may have deleted "buf", already entered it (e.g., when
// it did ":bunload") or aborted the script processing! // it did ":bunload") or aborted the script processing!
// If curwin->w_buffer is null, enter_buffer() will make it valid again // If curwin->w_buffer is null, enter_buffer() will make it valid again
if ((buf_valid(buf) && buf != curbuf && !aborting()) || curwin->w_buffer == NULL) { bool valid = buf_valid(buf);
enter_buffer(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) { if (old_tw != curbuf->b_p_tw) {
check_colorcolumn(curwin); check_colorcolumn(curwin);
} }

View File

@ -796,101 +796,102 @@ func ReadTestProtocol(name)
endfunc endfunc
func Test_locationlist() func Test_locationlist()
enew enew
augroup testgroup augroup testgroup
au! au!
autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>")) autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
augroup END augroup END
let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ] let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
let qflist = [] let qflist = []
for word in words for word in words
call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', }) call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', })
" NOTE: problem 1: " NOTE: problem 1:
" intentionally not setting 'lnum' so that the quickfix entries are not " intentionally not setting 'lnum' so that the quickfix entries are not
" valid " valid
eval qflist->setloclist(0, ' ') eval qflist->setloclist(0, ' ')
endfor endfor
" Test A " Test A
lrewind lrewind
enew enew
lopen lopen
4lnext 4lnext
vert split vert split
wincmd L wincmd L
lopen lopen
wincmd p wincmd p
lnext lnext
let fileName = expand("%") let fileName = expand("%")
wincmd p wincmd p
let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '') let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')
let fileName = substitute(fileName, '\\', '/', 'g') let fileName = substitute(fileName, '\\', '/', 'g')
let locationListFileName = substitute(locationListFileName, '\\', '/', 'g') let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')
call assert_equal("test://bar.txt", fileName) call assert_equal("test://bar.txt", fileName)
call assert_equal("test://bar.txt", locationListFileName) call assert_equal("test://bar.txt", locationListFileName)
wincmd n | only wincmd n | only
" Test B: " Test B:
lrewind lrewind
lopen lopen
2 2
exe "normal \<CR>" exe "normal \<CR>"
wincmd p wincmd p
3 3
exe "normal \<CR>" exe "normal \<CR>"
wincmd p wincmd p
4 4
exe "normal \<CR>" exe "normal \<CR>"
call assert_equal(2, winnr('$')) call assert_equal(2, winnr('$'))
wincmd n | only wincmd n | only
" Test C: " Test C:
lrewind lrewind
lopen lopen
" Let's move the location list window to the top to check whether it (the " 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: " first window found) will be reused when we try to open new windows:
wincmd K wincmd K
2 2
exe "normal \<CR>" exe "normal \<CR>"
wincmd p wincmd p
3 3
exe "normal \<CR>" exe "normal \<CR>"
wincmd p wincmd p
4 4
exe "normal \<CR>" exe "normal \<CR>"
1wincmd w 1wincmd w
call assert_equal('quickfix', &buftype) call assert_equal('quickfix', &buftype)
2wincmd w 2wincmd w
let bufferName = expand("%") let bufferName = expand("%")
let bufferName = substitute(bufferName, '\\', '/', 'g') let bufferName = substitute(bufferName, '\\', '/', 'g')
call assert_equal('test://quux.txt', bufferName) call assert_equal('test://quux.txt', bufferName)
wincmd n | only wincmd n | only
augroup! testgroup augroup! testgroup
endfunc endfunc
func Test_locationlist_curwin_was_closed() func Test_locationlist_curwin_was_closed()
augroup testgroup augroup testgroup
au! au!
autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>")) autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
augroup END augroup END
func! R(n) func! R(n)
quit quit
endfunc endfunc
new new
let q = [] let q = []
call add(q, {'filename': 'test_curwin.txt' }) call add(q, {'filename': 'test_curwin.txt' })
call setloclist(0, q) call setloclist(0, q)
call assert_fails('lrewind', 'E924:') call assert_fails('lrewind', 'E924:')
augroup! testgroup augroup! testgroup
delfunc R
endfunc endfunc
func Test_locationlist_cross_tab_jump() func Test_locationlist_cross_tab_jump()
@ -5489,4 +5490,20 @@ func Test_two_qf_windows()
%bw! %bw!
endfunc 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
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab