mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 9.1.1567: crash when using inline diff mode
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: #17805 Signed-off-by: Yee Cheng Chin <ychin.git@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
0e40501a9d
commit
c8b99e2d13
15
src/diff.c
15
src/diff.c
@@ -3391,6 +3391,11 @@ diff_find_change_inline_diff(
|
|||||||
diff_T *orig_diff = curtab->tp_first_diff;
|
diff_T *orig_diff = curtab->tp_first_diff;
|
||||||
curtab->tp_first_diff = NULL;
|
curtab->tp_first_diff = NULL;
|
||||||
|
|
||||||
|
// diff_read() also uses curtab->tp_diffbuf to determine what's an active
|
||||||
|
// buffer
|
||||||
|
buf_T *(orig_diffbuf[DB_COUNT]);
|
||||||
|
memcpy(orig_diffbuf, curtab->tp_diffbuf, sizeof(orig_diffbuf));
|
||||||
|
|
||||||
// Buffers to populate mmfile 1/2 that would be passed to xdiff as memory
|
// Buffers to populate mmfile 1/2 that would be passed to xdiff as memory
|
||||||
// files. Use a grow array as it is not obvious how much exact space we
|
// files. Use a grow array as it is not obvious how much exact space we
|
||||||
// need.
|
// need.
|
||||||
@@ -3412,7 +3417,12 @@ diff_find_change_inline_diff(
|
|||||||
continue; // skip buffer that isn't loaded
|
continue; // skip buffer that isn't loaded
|
||||||
|
|
||||||
if (dp->df_count[i] == 0)
|
if (dp->df_count[i] == 0)
|
||||||
continue; // skip buffer that don't have any texts in this block
|
{
|
||||||
|
// skip buffers that don't have any texts in this block so we don't
|
||||||
|
// end up marking the entire block as modified in multi-buffer diff
|
||||||
|
curtab->tp_diffbuf[i] = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (file1_idx == -1)
|
if (file1_idx == -1)
|
||||||
file1_idx = i;
|
file1_idx = i;
|
||||||
@@ -3626,7 +3636,7 @@ diff_find_change_inline_diff(
|
|||||||
CLEAR_FIELD(change);
|
CLEAR_FIELD(change);
|
||||||
for (int i = 0; i < DB_COUNT; i++)
|
for (int i = 0; i < DB_COUNT; i++)
|
||||||
{
|
{
|
||||||
if (new_diff->df_lnum[i] == 0)
|
if (new_diff->df_lnum[i] <= 0) // should never be < 0. Checking just for safety.
|
||||||
continue;
|
continue;
|
||||||
linenr_T diff_lnum = new_diff->df_lnum[i] - 1; // use zero-index
|
linenr_T diff_lnum = new_diff->df_lnum[i] - 1; // use zero-index
|
||||||
linenr_T diff_lnum_end = diff_lnum + new_diff->df_count[i];
|
linenr_T diff_lnum_end = diff_lnum + new_diff->df_count[i];
|
||||||
@@ -3675,6 +3685,7 @@ done:
|
|||||||
|
|
||||||
diff_clear(curtab);
|
diff_clear(curtab);
|
||||||
curtab->tp_first_diff = orig_diff;
|
curtab->tp_first_diff = orig_diff;
|
||||||
|
memcpy(curtab->tp_diffbuf, orig_diffbuf, sizeof(orig_diffbuf));
|
||||||
|
|
||||||
ga_clear(&file1_str);
|
ga_clear(&file1_str);
|
||||||
ga_clear(&file2_str);
|
ga_clear(&file2_str);
|
||||||
|
@@ -0,0 +1,20 @@
|
|||||||
|
| +0#0000e05#a8a8a8255@1|a+0#0000000#ffffff0|n|c|h|o|r|1| @10||+1&&| +0#0000e05#a8a8a8255@1|a+0#0000000#ffffff0|n|c|h|o|r|1| @7||+1&&| +0#0000e05#a8a8a8255@1|a+0#0000000#ffffff0|n|c|h|o|r|1| @8||+1&&| +0#0000e05#a8a8a8255@1|a+0#0000000#ffffff0|n|c|h|o|r|1| @7
|
||||||
|
| +0#0000e05#a8a8a8255@1|1+0#0000000#ffd7ff255|2+2&#ff404010|3|4|5|6|7|8|9|0+0&#ffd7ff255|a|b|c|d+2&#ff404010|e| +0&#ffd7ff255@2||+1&#ffffff0| +0#0000e05#a8a8a8255@1|1+0#0000000#ffd7ff255|2+2&#ff404010|3|4|5|6|7|-@1|0+0&#ffd7ff255|a|b|c|-+2&#ff404010|e||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@15||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|1+0#0000000#ffd7ff255|?+2&#ff404010@6|9|0+0&#ffd7ff255|a|b|c|d+2&#ff404010|?
|
||||||
|
| +0#0000e05#a8a8a8255@1|a+0#0000000#ffffff0|n|c|h|o|r|2| @10||+1&&| +0#0000e05#a8a8a8255@1|a+0#0000000#ffffff0|n|c|h|o|r|2| @7||+1&&| +0#0000e05#a8a8a8255@1|a+0#0000000#ffffff0|n|c|h|o|r|2| @8||+1&&| +0#0000e05#a8a8a8255@1|a+0#0000000#ffffff0|n|c|h|o|r|2| @7
|
||||||
|
|~+0#4040ff13&| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|~| @18||+1#0000000&|~+0#4040ff13&| @15||+1#0000000&|~+0#4040ff13&| @16||+1#0000000&|~+0#4040ff13&| @15
|
||||||
|
|X+3#0000000&|d|i|f|i|l|e|1| @1|1|,|1| @3|A|l@1| |<+1&&|d|i|f|i|l|e|2| |1|,|1| @1|A|l@1| |<|d|i|f|i|l|e|3| |1|,|1| @2|A|l@1| |<|d|i|f|i|l|e|4| |1|,|1| @1|A|l@1
|
||||||
|
|:+0&&> @73
|
@@ -2636,6 +2636,22 @@ func Test_diff_inline_multibuffer()
|
|||||||
call term_sendkeys(buf, ":diffthis\<CR>")
|
call term_sendkeys(buf, ":diffthis\<CR>")
|
||||||
call VerifyInternal(buf, "Test_diff_inline_multibuffer_06", " diffopt+=inline:char")
|
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)
|
call StopVimInTerminal(buf)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
@@ -719,6 +719,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1567,
|
||||||
/**/
|
/**/
|
||||||
1566,
|
1566,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user