mirror of
https://github.com/neovim/neovim.git
synced 2026-08-31 03:13:48 +00:00
vim-patch:9.1.2085: Use-after-free in winframe_remove()
Problem: Use-after-free in winframe_remove() (henices)
Solution: Set window_layout_locked() inside winframe_remove()
and check that writing diff files is disallowed when the
window layout is locked.
It can happen with a custom diff expression when removing a window:
1. Buffer was removed, so win_frame_remove() is called to remove the
window.
2. win_frame_remove() → frame_new_height() → scroll_to_fraction()
→ diff_check_fill() (checks for filler lines)
3. diff_check_fill() ends up causing a diff_try_update, and because we
are not using internal diff, it has to first write the file to a
buffer using buf_write()
4. buf_write() is called for a buffer that is not contained within a
window, so it first calls aucmd_prepbuf() to create a new temporary
window before writing the buffer and then later calls
aucmd_restbuf(), which restores the previous window layout, calling
winframe_remove() again, which will free the window/frame structure,
eventually freeing stuff that will still be accessed at step 2.
closes: vim/vim#19064
ead1dda74a
Nvim doesn't have this bug as Nvim uses a floating window as autocommand
window, and removing it doesn't need winframe_remove().
Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
@@ -3350,3 +3350,32 @@ describe("'diffanchors'", function()
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
-- oldtest: Test_diffexpr_wipe_buffers()
|
||||
it(':%bwipe does not crash when using diffexpr', function()
|
||||
local screen = Screen.new(70, 20)
|
||||
exec([[
|
||||
func DiffFuncExpr()
|
||||
let in = readblob(v:fname_in)
|
||||
let new = readblob(v:fname_new)
|
||||
let out = v:lua.vim.text.diff(in, new)
|
||||
call writefile(split(out, "\n"), v:fname_out)
|
||||
endfunc
|
||||
|
||||
new
|
||||
vnew
|
||||
set diffexpr=DiffFuncExpr()
|
||||
wincmd l
|
||||
new
|
||||
call setline(1,range(20))
|
||||
windo diffthis
|
||||
wincmd w
|
||||
hide
|
||||
%bw!
|
||||
]])
|
||||
screen:expect([[
|
||||
^ |
|
||||
{1:~ }|*18
|
||||
4 buffers wiped out |
|
||||
]])
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user