From 8543de3a862d55a762c130aa6a9d0e2a6c0b4838 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 25 Jul 2022 20:06:24 +0800 Subject: vim-patch:8.2.5163: crash when deleting buffers in diff mode Problem: Crash when deleting buffers in diff mode. Solution: Recompute diffs later. Skip window without a valid buffer. https://github.com/vim/vim/commit/cd38bb4d83c942c4bad596835c6766cbf32e5195 --- src/nvim/diff.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/nvim/diff.c') diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 75021e90d6..136fc5402b 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -115,7 +115,10 @@ void diff_buf_delete(buf_T *buf) tp->tp_diff_invalid = true; if (tp == curtab) { - diff_redraw(true); + // don't redraw right away, more might change or buffer state + // is invalid right now + need_diff_redraw = true; + redraw_later(curwin, VALID); } } } @@ -648,7 +651,8 @@ void diff_redraw(bool dofold) need_diff_redraw = false; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (!wp->w_p_diff) { + // when closing windows or wiping buffers skip invalid window + if (!wp->w_p_diff || !buf_valid(wp->w_buffer)) { continue; } redraw_later(wp, SOME_VALID); -- cgit From 771564b00e5b64ac74be443dde84e160bc7fce05 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 25 Jul 2022 20:09:23 +0800 Subject: vim-patch:8.2.5164: invalid memory access after diff buffer manipulations Problem: Invalid memory access after diff buffer manipulations. Solution: Use zero offset when change removes all lines in a diff block. https://github.com/vim/vim/commit/c101abff4c6756db4f5e740fde289decb9452efa --- src/nvim/diff.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/nvim/diff.c') diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 136fc5402b..55d8b7e36b 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -372,9 +372,8 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T // 2. 3. 4. 5.: inserted/deleted lines touching this diff. if (deleted > 0) { + off = 0; if (dp->df_lnum[idx] >= line1) { - off = dp->df_lnum[idx] - lnum_deleted; - if (last <= line2) { // 4. delete all lines of diff if ((dp->df_next != NULL) @@ -391,14 +390,13 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T dp->df_count[idx] = 0; } else { // 5. delete lines at or just before top of diff + off = dp->df_lnum[idx] - lnum_deleted; n = off; dp->df_count[idx] -= line2 - dp->df_lnum[idx] + 1; check_unchanged = true; } dp->df_lnum[idx] = line1; } else { - off = 0; - if (last < line2) { // 2. delete at end of diff dp->df_count[idx] -= last - lnum_deleted + 1; -- cgit From 79872f377019614467a8e03049fb47c067331804 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 27 Jul 2022 07:26:32 +0800 Subject: fix(options): properly free string options (#19510) --- src/nvim/diff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/diff.c') diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 55d8b7e36b..4ade6072e6 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -1423,7 +1423,7 @@ void diff_win_options(win_T *wp, int addbuf) } wp->w_p_fdc_save = vim_strsave(wp->w_p_fdc); } - xfree(wp->w_p_fdc); + free_string_option(wp->w_p_fdc); wp->w_p_fdc = (char_u *)xstrdup("2"); assert(diff_foldcolumn >= 0 && diff_foldcolumn <= 9); snprintf((char *)wp->w_p_fdc, STRLEN(wp->w_p_fdc) + 1, "%d", diff_foldcolumn); -- cgit From 352a177dae5b602f5685faa3ce4ad841d3ddbc15 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 29 Jul 2022 06:53:32 +0800 Subject: vim-patch:9.0.0026: accessing freed memory with diff put (#19564) Problem: Accessing freed memory with diff put. Solution: Bail out when diff pointer is no longer valid. https://github.com/vim/vim/commit/c5274dd12224421f2430b30c53b881b9403d649e --- src/nvim/diff.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src/nvim/diff.c') diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 4ade6072e6..59a1ce9932 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -2487,6 +2487,17 @@ void nv_diffgetput(bool put, size_t count) ex_diffgetput(&ea); } +/// Return true if "diff" appears in the list of diff blocks of the current tab. +static bool valid_diff(diff_T *diff) +{ + for (diff_T *dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) { + if (dp == diff) { + return true; + } + } + return false; +} + /// ":diffget" and ":diffput" /// /// @param eap @@ -2744,10 +2755,9 @@ void ex_diffgetput(exarg_T *eap) } } - // Adjust marks. This will change the following entries! if (added != 0) { - mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, added, - kExtmarkUndo); + // Adjust marks. This will change the following entries! + mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, added, kExtmarkUndo); if (curwin->w_cursor.lnum >= lnum) { // Adjust the cursor position if it's in/after the changed // lines. @@ -2764,7 +2774,15 @@ void ex_diffgetput(exarg_T *eap) // Diff is deleted, update folds in other windows. diff_fold_update(dfree, idx_to); xfree(dfree); - } else { + } + + // mark_adjust() may have made "dp" invalid. We don't know where + // to continue then, bail out. + if (added != 0 && !valid_diff(dp)) { + break; + } + + if (dfree == NULL) { // mark_adjust() may have changed the count in a wrong way dp->df_count[idx_to] = new_count; } -- cgit From 88ed33230ac91423f6e09c3f7c07cc02b2b115ac Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 29 Jul 2022 07:31:54 +0800 Subject: vim-patch:9.0.0101: invalid memory access in diff mode with "dp" and undo (#19568) Problem: Invalid memory access in diff mode with "dp" and undo. Solution: Make sure the line number does not go below one. https://github.com/vim/vim/commit/4e677b9c40ccbc5f090971b31dc2fe07bf05541d --- src/nvim/diff.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/nvim/diff.c') diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 59a1ce9932..f43eaaa299 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -419,10 +419,13 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T } } - int i; - for (i = 0; i < DB_COUNT; i++) { + for (int i = 0; i < DB_COUNT; i++) { if ((tp->tp_diffbuf[i] != NULL) && (i != idx)) { - dp->df_lnum[i] -= off; + if (dp->df_lnum[i] > off) { + dp->df_lnum[i] -= off; + } else { + dp->df_lnum[i] = 1; + } dp->df_count[i] += n; } } @@ -2707,8 +2710,9 @@ void ex_diffgetput(exarg_T *eap) for (i = 0; i < count; i++) { // remember deleting the last line of the buffer buf_empty = curbuf->b_ml.ml_line_count == 1; - ml_delete(lnum, false); - added--; + if (ml_delete(lnum, false) == OK) { + added--; + } } for (i = 0; i < dp->df_count[idx_from] - start_skip - end_skip; i++) { -- cgit From 824a729628950d72834b98faf28d18b7a94eefb2 Mon Sep 17 00:00:00 2001 From: Dundar Goc Date: Tue, 19 Jul 2022 15:30:57 +0200 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/diff.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/diff.c') diff --git a/src/nvim/diff.c b/src/nvim/diff.c index f43eaaa299..4ad2591802 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -3066,8 +3066,8 @@ static int parse_diff_ed(char_u *line, diffhunk_T *hunk) // change: {first}[,{last}]c{first}[,{last}] // append: {first}a{first}[,{last}] // delete: {first}[,{last}]d{first} - char_u *p = line; - linenr_T f1 = getdigits_int32((char **)&p, true, 0); + char *p = (char *)line; + linenr_T f1 = getdigits_int32(&p, true, 0); if (*p == ',') { p++; l1 = getdigits(&p, true, 0); @@ -3077,7 +3077,7 @@ static int parse_diff_ed(char_u *line, diffhunk_T *hunk) if (*p != 'a' && *p != 'c' && *p != 'd') { return FAIL; // invalid diff format } - int difftype = *p++; + int difftype = (uint8_t)(*p++); long f2 = getdigits(&p, true, 0); if (*p == ',') { p++; @@ -3114,7 +3114,7 @@ static int parse_diff_unified(char_u *line, diffhunk_T *hunk) { // Parse unified diff hunk header: // @@ -oldline,oldcount +newline,newcount @@ - char_u *p = line; + char *p = (char *)line; if (*p++ == '@' && *p++ == '@' && *p++ == ' ' && *p++ == '-') { long oldcount; long newline; -- cgit From c9ca90229b9b46782cad83502caaccaa7520dc0d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 1 Aug 2022 06:05:29 +0800 Subject: vim-patch:9.0.0124: code has more indent than needed Problem: Code has more indent than needed. Solution: Use continue and return statements. (closes vim/vim#10824) https://github.com/vim/vim/commit/101d57b34b72f4fbc7df1b6edfd64c64a6be14fc --- src/nvim/diff.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/nvim/diff.c') diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 4ad2591802..849204f789 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -656,6 +656,7 @@ void diff_redraw(bool dofold) if (!wp->w_p_diff || !buf_valid(wp->w_buffer)) { continue; } + redraw_later(wp, SOME_VALID); if (wp != curwin) { wp_other = wp; @@ -664,8 +665,8 @@ void diff_redraw(bool dofold) foldUpdateAll(wp); } - // A change may have made filler lines invalid, need to take care - // of that for other windows. + // A change may have made filler lines invalid, need to take care of + // that for other windows. int n = diff_check(wp, wp->w_topline); if (((wp != curwin) && (wp->w_topfill > 0)) || (n > 0)) { @@ -682,6 +683,7 @@ void diff_redraw(bool dofold) check_topfill(wp, false); } } + if (wp_other != NULL && curwin->w_p_scb) { if (used_max_fill_curwin) { // The current window was set to use the maximum number of filler -- cgit