vim-patch:9.1.1567: crash when using inline diff mode (#35005)

Problem:  Crash when using inline diff mode
          (Ilya Grigoriev)
Solution: Set tp_diffbuf to NULL when skipping a diff block
          (Yee Cheng Chin).

Fix an array out of bounds crash when using diffopt+=inline:char when 4
or more buffers are being diff'ed. This happens when one of the blocks
is empty. The inline highlight logic skips using that buffer's block,
but when another buffer is used later and calls diff_read() to merge the
diff blocks together, it could erroneously consider the empty block's
diff info which has not been initialized, leaving to diff numbers that
are invalid. Later on the diff num is used without bounds checking which
leads to the crash.

Fix this by making sure to unset tp_diffbuf to NULL when we skip a
block, so diff_read() will not consider this buffer to be used within
inline diff. Also, add more bounds checking just to be safe.

closes: vim/vim#17805

c8b99e2d13

Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
This commit is contained in:
zeertzjq
2025-07-20 21:11:43 +08:00
committed by GitHub
parent 14cafbcc85
commit b91613f42c
3 changed files with 54 additions and 2 deletions

View File

@@ -2384,6 +2384,22 @@ func Test_diff_inline_multibuffer()
call term_sendkeys(buf, ":diffthis\<CR>")
call VerifyInternal(buf, "Test_diff_inline_multibuffer_06", " diffopt+=inline:char")
call StopVimInTerminal(buf)
endfunc
" Test that when using multi-buffer diff, an empty block would be correctly
" skipped in the result, without resulting in invalid states or crashes.
func Test_diff_inline_multibuffer_empty_block()
CheckScreendump
call writefile(['anchor1', '1234567890abcde', 'anchor2'], 'Xdifile1')
call writefile(['anchor1', '1234567--0abc-e', 'anchor2'], 'Xdifile2')
call writefile(['anchor1', 'anchor2'], 'Xdifile3')
call writefile(['anchor1', '1???????90abcd?', 'anchor2'], 'Xdifile4')
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3 Xdifile4', {})
call VerifyInternal(buf, "Test_diff_inline_multibuffer_empty_block_01", " diffopt+=inline:char")
call StopVimInTerminal(buf)
endfunc